Skip to content

Instantly share code, notes, and snippets.

@timblair
Last active August 29, 2015 14:16
Show Gist options
  • Save timblair/9e8787f4e4721e1f5a71 to your computer and use it in GitHub Desktop.
Save timblair/9e8787f4e4721e1f5a71 to your computer and use it in GitHub Desktop.
RFC 5322-compliant Message ID generator
require "date"
class MessageID
module Decode
STAMP_FIELD_FORMAT = "%Y%m%d%H%M%S%N"
def self.decode(id)
user, host = id.split("@")
parts = user.split(".").map { |part| part.to_i(36) }
stamp, ident = parts.shift, []
while (parts.length > 1) do ident << parts.shift; end
counter = parts.last
stamp = DateTime.strptime(stamp.to_s, STAMP_FIELD_FORMAT)
{
stamp: stamp.strftime("%Y-%m-%d %H:%M:%S.%6N"),
ident: ident,
counter: counter,
host: host
}
end
end
end
ids = %w{
493c39w9zx13q.b4tn3y.2ato@437783-daemon6.lon3.whitelabeldating.com
493c39wjpvh8y.xgp16n.85h17@428180-daemon5.lon3.whitelabeldating.com
493c39wtz5dnq.qgja3v.tyz1t@370845-daemon4.lon3.whitelabeldating.com
493c39x0su3js.rz53nu.1hx9k@370843-daemon2.lon3.whitelabeldating.com
}
ids.each { |id| p MessageID::Decode.decode(id) }
require "socket"
class MessageID
UnsupportedFormatException = Class.new(StandardError)
MESSAGE_ID_FORMAT = "<%s.%s.%s%s@%s>"
STAMP_FIELD_FORMAT = "%Y%m%d%H%M%S%6N"
def initialize(*ident)
@ident = ident.compact.flatten
@ident << Random.rand(999_999_999) if @ident.empty?
end
def id(format=:short)
raise(UnsupportedFormatException) unless %I{ short long }.include?(format)
sprintf(MESSAGE_ID_FORMAT, *fields(format == :short))
end
alias :to_str :id
alias :to_s :id
private
def timestamp
@timestamp ||= Time.now.utc
end
def random_id
@random_id ||= Random.rand(999_999_999)
end
def fields(shorten)
values = [
timestamp.strftime(STAMP_FIELD_FORMAT).to_i,
(shorten ? base36ify(@ident) : @ident).join("."),
Process.pid,
random_id,
Socket.gethostname
]
shorten ? base36ify(values) : values
end
def base36ify(fields)
fields.collect { |v| v.is_a?(Integer) ? v.to_s(36) : v }
end
end
puts MessageID.new #=> <[email protected]>
5.times { puts MessageID.new }
#=> <[email protected]>
# <[email protected]>
# <[email protected]>
# <[email protected]>
# <[email protected]>
msgid = MessageID.new(20_345_678, 23_456, 23, 234)
puts msgid #=> <[email protected]>
puts msgid.to_s(:long) #=> <20150302113621373199.20345678.23456.23.234.46356561149270@host.local>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment