Skip to content
Browse files

ZOMG DOCS

  • Loading branch information...
1 parent 3114f24 commit 2afde53586787986147cc72ad66783ec4a65598a @jhawthorn committed Apr 15, 2012
Showing with 117 additions and 65 deletions.
  1. +48 −59 README.md
  2. +58 −5 lib/dkim/options.rb
  3. +11 −1 lib/dkim/signed_mail.rb
View
107 README.md
@@ -1,45 +1,18 @@
dkim
====
+A DKIM signing library in ruby.
+
[![Build Status](https://secure.travis-ci.org/jhawthorn/dkim.png?branch=master)](http://travis-ci.org/jhawthorn/dkim)
-A DKIM signing library in ruby.
+[Documentation](http://rubydoc.info/github/jhawthorn/dkim)
Installation
============
sudo gem install dkim
-Usage
-=====
-
-Calling `Dkim.sign` on a string representing an email message returns the message with a DKIM signature inserted.
-
-For example
-
- mail = <<eos
- To: someone@example.com
- From: john@example.com
- Subject: hi
-
- Howdy
- eos
-
- Dkim.sign(mail)
-
- # =>
- # To: someone@example.com
- # From: john@example.com
- # Subject: hi
- # DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; q=dns/txt; s=mail; t=1305917829;
- # bh=qZxwTnSM1ywsrq0Ag9UhQSOtVIG+sW5zDkB+hPbuX08=; h=from:subject:to;
- # b=0mKnNOkxFGiww63Zu4t46J7eZc3Uak3I9km3IH2Le3XcnSNtWJgxiwBX26IZ5yzcT
- # VwJzcCnPKCScIJMQ7yfbfXmNsKVIOV6eSUqu1YvJ1fgzlSAXuDEMNFTjoto5rrdA+
- # BgX849hEY/bWHDl1JJgNpiwtpl4t0Q7M4BVJUd7Lo=
- #
- # Howdy
-
Necessary configuration
------------------------
+=======================
A private key, a domain, and a selector need to be specified in order to sign messages.
These can be specified globally
@@ -52,31 +25,12 @@ Options can be overridden per message.
Dkim.sign(mail, :selector => 'mail2', :private_key => open('private2.pem').read)
-Additional configuration
-------------------------
-
-The following is the default configuration
-
- Dkim::signable_headers = Dkim::DefaultHeaders # Sign only the specified headers
- Dkim::signing_algorithm = 'rsa-sha256' # can be rsa-sha1 or rsa-sha256 (default)
- Dkim::header_canonicalization = 'relaxed' # Can be simple or relaxed (default)
- Dkim::body_canonicalization = 'relaxed' # Can be simple or relaxed (default)
-
-The defaults should fit most users needs; however, certain use cases will need them to be customized.
-
-For example, for sending mesages through amazon SES, certain headers should not be signed
-
- Dkim::signable_headers = Dkim::DefaultHeaders - %w{Message-ID Resent-Message-ID Date Return-Path Bounces-To}
-
-RFC 6376 states that signers SHOULD sign using rsa-sha256. For this reason, dkim will *not* use rsa-sha1 as a fallback if the openssl library does not support sha256.
-If you wish to override this behaviour and use whichever algorithm is available you can use this snippet (**not recommended**).
-
- Dkim::signing_algorithm = defined?(OpenSSL::Digest::SHA256) ? 'rsa-sha256' : 'rsa-sha1'
+For more details see {Dkim::Options}
Usage With Rails
================
-Dkim contains `Dkim::Interceptor` which can be used to sign all mail delivered by the [mail gem](https://github.com/mikel/mail) or rails 3, which uses mail.
+Dkim contains `Dkim::Interceptor` which can be used to sign all mail delivered by rails 3 or [mail](https://github.com/mikel/mail).
For rails, create an initializer (for example `config/initializers/dkim.rb`) with the following template.
# Configure dkim globally (see above)
@@ -87,14 +41,49 @@ For rails, create an initializer (for example `config/initializers/dkim.rb`) wit
# This will sign all ActionMailer deliveries
ActionMailer::Base.register_interceptor(Dkim::Interceptor)
-Example executable
-==================
+Standalone Usage
+================
-The library includes a `dkimsign.rb` executable suitable for testing the library or performing simple signatures.
+Calling `Dkim.sign` on a string representing an email message returns the message with a DKIM signature inserted.
-`dkimsign.rb DOMAIN SELECTOR KEYFILE [MAILFILE]`
+For example
-If MAILFILE is not specified `dkimsign.rb` will read the mail message from standard in.
+ mail = Dkim.sign(<<EOS)
+ To: someone@example.com
+ From: john@example.com
+ Subject: hi
+
+ Howdy
+ EOS
+
+ Dkim.sign(mail)
+ # =>
+ # To: someone@example.com
+ # From: john@example.com
+ # Subject: hi
+ # DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; q=dns/txt; s=mail; t=1305917829;
+ # bh=qZxwTnSM1ywsrq0Ag9UhQSOtVIG+sW5zDkB+hPbuX08=; h=from:subject:to;
+ # b=0mKnNOkxFGiww63Zu4t46J7eZc3Uak3I9km3IH2Le3XcnSNtWJgxiwBX26IZ5yzcT
+ # VwJzcCnPKCScIJMQ7yfbfXmNsKVIOV6eSUqu1YvJ1fgzlSAXuDEMNFTjoto5rrdA+
+ # BgX849hEY/bWHDl1JJgNpiwtpl4t0Q7M4BVJUd7Lo=
+ #
+ # Howdy
+
+More flexibility can be found using {Dkim::SignedMail} directly.
+
+Specific configuration
+========================
+
+For sending mesages through Amazon SES, certain headers should not be signed
+
+ Dkim::signable_headers = Dkim::DefaultHeaders - %w{Message-ID Resent-Message-ID Date Return-Path Bounces-To}
+
+Some OpenSSL's don't have sha256 support.
+RFC 6376 states that signers SHOULD sign using rsa-sha256.
+For this reason, dkim will *not* use rsa-sha1 as a fallback.
+If you wish to override this behaviour and use whichever algorithm is available you can use this snippet (**not recommended**).
+
+ Dkim::signing_algorithm = defined?(OpenSSL::Digest::SHA256) ? 'rsa-sha256' : 'rsa-sha1'
Limitations
===========
@@ -112,8 +101,8 @@ Resources
* [RFC 6376](http://tools.ietf.org/html/rfc6376)
* Inspired by perl's [Mail-DKIM](http://dkimproxy.sourceforge.net/)
-Copyright
-=========
+License
+=======
(The MIT License)
View
63 lib/dkim/options.rb
@@ -1,16 +1,69 @@
module Dkim
module Options
- ATTRIBUTES = :time, :private_key, :signing_algorithm, :signable_headers, :domain, :selector, :time, :header_canonicalization, :body_canonicalization
+ private
+ def self.define_option_method attribute_name
+ define_method(attribute_name){options[attribute_name]}
+ define_method("#{attribute_name}="){|value| options[attribute_name] = value}
+ end
+ public
+
+ # @attribute [rw]
+ # Hash of all options
+ # @return [Hash]
def options
@options ||= {}
end
attr_writer :options
- ATTRIBUTES.each do |attribute_name|
- define_method(attribute_name){options[attribute_name]}
- define_method("#{attribute_name}="){|value| options[attribute_name] = value}
- end
+ # @attribute [rw]
+ # This corresponds to the t= tag in the dkim header.
+ # The default (nil) is to use the current time at signing.
+ # @return [Time,#to_i] A Time object or seconds since the epoch
+ define_option_method :time
+
+ # @attribute [rw]
+ # The signing algorithm for dkim. Valid values are 'rsa-sha1' and 'rsa-sha256' (default).
+ # This corresponds to the a= tag in the dkim header.
+ # @return [String] signing algorithm
+ define_option_method :signing_algorithm
+
+ # @attribute [rw]
+ # Configures which headers should be signed.
+ # Defaults to {Dkim::DefaultHeaders Dkim::DefaultHeaders}
+ # @return [Array<String>] signable headers
+ define_option_method :signable_headers
+
+ # @attribute [rw]
+ # The domain used for signing.
+ # This corresponds to the d= tag in the dkim header.
+ # @return [String] domain
+ define_option_method :domain
+
+ # @attribute [rw]
+ # Selector used for signing.
+ # This corresponds to the s= tag in the dkim header.
+ # @return [String] selector
+ define_option_method :selector
+
+ # @attribute [rw]
+ # Header canonicalization algorithm.
+ # Valid values are 'simple' and 'relaxed' (default)
+ # This corresponds to the first half of the c= tag in the dkim header.
+ # @return [String] header canonicalization algorithm
+ define_option_method :header_canonicalization
+
+ # @attribute [rw]
+ # Body canonicalization algorithm.
+ # Valid values are 'simple' and 'relaxed' (default)
+ # This corresponds to the second half of the c= tag in the dkim header.
+ # @return [String] body canonicalization algorithm
+ define_option_method :body_canonicalization
+ # @attribute [rw]
+ # RSA private key for signing.
+ # Can be assigned either an {OpenSSL::PKey::RSA} private key or a valid PEM format string.
+ # @return [OpenSSL::PKey::RSA] private key
+ define_option_method :private_key
def private_key= key
key = OpenSSL::PKey::RSA.new(key) if key.is_a?(String)
options[:private_key] = key
View
12 lib/dkim/signed_mail.rb
@@ -10,6 +10,10 @@ module Dkim
class SignedMail
include Options
+ # A new instance of SignedMail
+ #
+ # @param [String,#to_s] message mail message to be signed
+ # @param [Hash] options hash of options for signing. Defaults are taken from {Dkim}. See {Options} for details.
def initialize message, options={}
message = message.to_s.gsub(/\r?\n/, "\r\n")
headers, body = message.split(/\r?\n\r?\n/, 2)
@@ -20,18 +24,24 @@ def initialize message, options={}
@options = Dkim.options.merge(options)
end
+ # @return [Array<String>] Signed headers of message in their canonical forms
def signed_headers
(@headers.map(&:relaxed_key) & signable_headers.map(&:downcase)).sort
end
+
+ # @return [String] Signed headers of message in their canonical forms
def canonical_header
headers = signed_headers.map do |key|
@headers[key].to_s(header_canonicalization) + "\r\n"
end.join
end
+
+ # @return [String] Body of message in its canonical form
def canonical_body
@body.to_s(body_canonicalization)
end
+ # @return [DkimHeader] Constructed signature for the mail message
def dkim_header
dkim_header = DkimHeader.new
@@ -62,8 +72,8 @@ def dkim_header
dkim_header
end
+ # @return [String] Message combined with calculated dkim header signature
def to_s
- # Return the original message with the calculated header
headers = @headers.to_a + [dkim_header]
headers.map(&:to_s).join("\r\n") +
"\r\n\r\n" +

0 comments on commit 2afde53

Please sign in to comment.
Something went wrong with that request. Please try again.