Class: Dkim::SignedMail

Inherits:
Object
  • Object
show all
Includes:
Options
Defined in:
lib/dkim/signed_mail.rb

Instance Attribute Summary

Attributes included from Options

#body_canonicalization, #domain, #header_canonicalization, #identity, #options, #private_key, #selector, #signable_headers, #signing_algorithm, #time

Instance Method Summary collapse

Constructor Details

#initialize(message, options = {}) ⇒ SignedMail

A new instance of SignedMail

Parameters:

  • message (String, #to_s)

    mail message to be signed

  • options (Hash) (defaults to: {})

    hash of options for signing. Defaults are taken from Dkim. See Options for details.



17
18
19
20
21
22
23
24
25
26
# File 'lib/dkim/signed_mail.rb', line 17

def initialize message, options={}
  message = message.to_s.gsub(/\r?\n/, "\r\n")
  headers, body = message.split(/\r?\n\r?\n/, 2)
  @original_message = message
  @headers = Header.parse headers
  @body    = Body.new body

  # default options from Dkim.options
  @options = Dkim.options.merge(options)
end

Instance Method Details

#canonical_bodyString

Returns Body of message in its canonical form.

Returns:

  • (String)

    Body of message in its canonical form



45
46
47
# File 'lib/dkim/signed_mail.rb', line 45

def canonical_body
  @body.to_s(body_canonicalization)
end

#canonical_headerString

Returns Signed headers of message in their canonical forms.

Returns:

  • (String)

    Signed headers of message in their canonical forms



40
41
42
# File 'lib/dkim/signed_mail.rb', line 40

def canonical_header
  canonicalized_headers.to_s(header_canonicalization)
end

#canonicalized_headersObject



28
29
30
# File 'lib/dkim/signed_mail.rb', line 28

def canonicalized_headers
  CanonicalizedHeaders.new(@headers, signed_headers)
end

#dkim_headerDkimHeader

Returns Constructed signature for the mail message.

Returns:

  • (DkimHeader)

    Constructed signature for the mail message



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/dkim/signed_mail.rb', line 50

def dkim_header
  dkim_header = DkimHeader.new

  raise "A private key is required" unless private_key
  raise "A domain is required"      unless domain
  raise "A selector is required"    unless selector

  # Add basic DKIM info
  dkim_header['v'] = '1'
  dkim_header['a'] = signing_algorithm
  dkim_header['c'] = "#{header_canonicalization}/#{body_canonicalization}"
  dkim_header['d'] = domain
  dkim_header['i'] = identity if identity
  dkim_header['q'] = 'dns/txt'
  dkim_header['s'] = selector
  dkim_header['t'] = (time || Time.now).to_i

  # Add body hash and blank signature
  dkim_header['bh']= digest_alg.digest(canonical_body)
  dkim_header['h'] = signed_headers.join(':')
  dkim_header['b'] = ''

  # Calculate signature based on intermediate signature header
  headers = canonical_header
  headers << dkim_header.to_s(header_canonicalization)
  dkim_header['b'] = private_key.sign(digest_alg, headers)

  dkim_header
end

#signed_headersArray<String>

Returns lowercased names of headers in the order they are signed.

Returns:

  • (Array<String>)

    lowercased names of headers in the order they are signed



33
34
35
36
37
# File 'lib/dkim/signed_mail.rb', line 33

def signed_headers
  @headers.map(&:relaxed_key).select do |key|
    signable_headers.map(&:downcase).include?(key)
  end
end

#to_sString

Returns Message combined with calculated dkim header signature.

Returns:

  • (String)

    Message combined with calculated dkim header signature



81
82
83
# File 'lib/dkim/signed_mail.rb', line 81

def to_s
  dkim_header.to_s + "\r\n" + @original_message
end