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 #=> <493bxydx7qi5h.52p76a.10bvae8w0@host.local>
5.times { puts MessageID.new }
#=> <493bxydx7qi5h.52p76a.10bvae8w0@host.local>
# <493bxydx7qi62.22u8jg.10bvcz4bld@host.local>
# <493bxydx7qi6m.w829m.10bv9e8v5f@host.local>
# <493bxydx7qi73.batkan.10bv5cx20x@host.local>
# <493bxydx7qi7j.eg3gvy.10bvaa6h31@host.local>
msgid = MessageID.new(20_345_678, 23_456, 23, 234)
puts msgid #=> <493bxydqj4y6n.c42tq.i3k.n.6i.zro9a3djq@host.local>
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