Skip to content

Commit

Permalink
A lot of documentation patches to the mail and utils and net files. A…
Browse files Browse the repository at this point in the history
…lso added "log/BugTrackingLog.txt" for myself as my bug log got clobbered by the new changelog.txt format.
  • Loading branch information
mikel committed Mar 1, 2008
1 parent 57f47fb commit 9680049
Show file tree
Hide file tree
Showing 8 changed files with 2,588 additions and 1,123 deletions.
3 changes: 3 additions & 0 deletions CHANGES
@@ -1,7 +1,10 @@
=== 1.2.2 / ?

* A _LOT_ more documentation...!
* More documentation - (Mikel)
* Applied Ruby 1.9 patches to the library - All tests passing now - (Mikel)
* Closed #17719 - Fixed UNIXMbox code - readonly was not working and raising an exception. Now works.
* Closed #18038 - Multiple froms not being parsed correctly, added a test case to cover this and show the correct handling - (Mikel)

=== 1.2.1 / 2008-01-11

Expand Down
1 change: 1 addition & 0 deletions lib/tmail.rb
Expand Up @@ -2,3 +2,4 @@
require 'tmail/mail'
require 'tmail/mailbox'
require 'tmail/core_extensions'
require 'tmail/net'
39 changes: 37 additions & 2 deletions lib/tmail/mail.rb
Expand Up @@ -83,20 +83,49 @@ module TMail
class Mail

class << self

# Opens an email that has been saved out as a file by itself.
#
# This function will read a file non-destructively and then parse
# the contents and return a TMail::Mail object.
#
# Does not handle multiple email mailboxes (like a unix mbox) for that
# use the TMail::UNIXMbox class.
#
# Example:
# mail = TMail::Mail.load('filename')
#
def load( fname )
new(FilePort.new(fname))
end

alias load_from load
alias loadfrom load


# Parses an email from the supplied string and returns a TMail::Mail
# object.
#
# Example:
# require 'rubygems'; require 'tmail'
# email_string =<<HEREDOC
# To: mikel@lindsaar.net
# From: mikel@me.com
# Subject: This is a short Email
#
# Hello there Mikel!
#
# HEREDOC
# mail = TMail::Mail.parse(email_string)
# #=> #<TMail::Mail port=#<TMail::StringPort:id=0xa30ac0> bodyport=nil>
# mail.body
# #=> "Hello there Mikel!\n\n"
def parse( str )
new(StringPort.new(str))
end

end

def initialize( port = nil, conf = DEFAULT_CONFIG )
def initialize( port = nil, conf = DEFAULT_CONFIG ) #:nodoc:
@port = port || StringPort.new
@config = Config.to_config(conf)

Expand All @@ -112,6 +141,12 @@ def initialize( port = nil, conf = DEFAULT_CONFIG )
}
end

# Provides access to the port this email is using to hold it's data
#
# Example:
# mail = TMail::Mail.parse(email_string)
# mail.port
# #=> #<TMail::StringPort:id=0xa2c952>
attr_reader :port

def inspect
Expand Down
31 changes: 16 additions & 15 deletions lib/tmail/net.rb
@@ -1,8 +1,3 @@
=begin rdoc
= Net provides SMTP wrapping
=end
#--
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
#
Expand All @@ -29,13 +24,14 @@
# with permission of Minero Aoki.
#++

#:stopdoc:
require 'nkf'

#:startdoc:

module TMail

class Mail

def send_to( smtp )
do_send_to(smtp) do
ready_to_send
Expand Down Expand Up @@ -131,7 +127,7 @@ def mime_encode_multipart( top = true )

end


#:stopdoc:
class DeleteFields

NOSEND_FIELDS = %w(
Expand All @@ -155,8 +151,9 @@ def exec( mail )
end

end
#:startdoc:


#:stopdoc:
class AddMessageId

def initialize( fqdn = nil )
Expand All @@ -170,17 +167,19 @@ def exec( mail )
end

end
#:startdoc:


#:stopdoc:
class AddDate

def exec( mail )
mail.date = Time.now
end

end
#:startdoc:


#:stopdoc:
class MimeEncodeAuto

def initialize( s = nil, m = nil )
Expand All @@ -198,8 +197,9 @@ def exec( mail )
end

end

#:startdoc:

#:stopdoc:
class MimeEncodeSingle

def exec( mail )
Expand All @@ -225,8 +225,9 @@ def on_binary( body )
end

end


#:startdoc:

#:stopdoc:
class MimeEncodeMulti

def exec( mail, top = true )
Expand All @@ -243,5 +244,5 @@ def exec( mail, top = true )
end

end

#:startdoc:
end # module TMail
76 changes: 56 additions & 20 deletions lib/tmail/utils.rb
Expand Up @@ -52,19 +52,45 @@
# check out TMail::Mail, TMail::Address and TMail::Headers for other lists.
module TMail

# Provides an exception to throw on errors in Syntax within TMail's parsers
class SyntaxError < StandardError; end


# Provides a new email boundary to separate parts of the email. This is a random
# string based off the current time, so should be fairly unique.
#
# For Example:
#
# TMail.new_boundary
# #=> "mimepart_47bf656968207_25a8fbb80114"
# TMail.new_boundary
# #=> "mimepart_47bf66051de4_25a8fbb80240"
def TMail.new_boundary
'mimepart_' + random_tag
end

# Provides a new email message ID. You can use this to generate unique email message
# id's for your email so you can track them.
#
# Optionally takes a fully qualified domain name (default to the current hostname
# returned by Socket.gethostname) that will be appended to the message ID.
#
# For Example:
#
# email.message_id = TMail.new_message_id
# #=> "<47bf66845380e_25a8fbb80332@baci.local.tmail>"
# email.to_s
# #=> "Message-Id: <47bf668b633f1_25a8fbb80475@baci.local.tmail>\n\n"
# email.message_id = TMail.new_message_id("lindsaar.net")
# #=> "<47bf668b633f1_25a8fbb80475@lindsaar.net.tmail>"
# email.to_s
# #=> "Message-Id: <47bf668b633f1_25a8fbb80475@lindsaar.net.tmail>\n\n"
def TMail.new_message_id( fqdn = nil )
fqdn ||= ::Socket.gethostname
"<#{random_tag()}@#{fqdn}.tmail>"
end

def TMail.random_tag
#:stopdoc:
def TMail.random_tag #:nodoc:
@uniq += 1
t = Time.now
sprintf('%x%x_%x%x%d%x',
Expand All @@ -75,8 +101,13 @@ def TMail.random_tag

@uniq = 0

#:startdoc:

# Text Utils provides a namespace to define TOKENs, ATOMs, PHRASEs and CONTROL characters that
# are OK per RFC 2822.
#
# It also provides methods you can call to determine if a string is safe
module TextUtils
# Defines characters per RFC that are OK for TOKENs, ATOMs, PHRASEs and CONTROL characters.

aspecial = '()<>[]:;.\\,"'
tspecial = '()<>[];:\\,"/?='
Expand All @@ -88,37 +119,37 @@ module TextUtils
TOKEN_UNSAFE = /[#{Regexp.quote tspecial}#{control}#{lwsp}]/n
CONTROL_CHAR = /[#{control}]/n

# Returns true if the string supplied is free from characters not allowed as an ATOM
def atom_safe?( str )
# Returns true if the string supplied is free from characters not allowed as an ATOM
not ATOM_UNSAFE === str
end

# If the string supplied has ATOM unsafe characters in it, will return the string quoted
# in double quotes, otherwise returns the string unmodified
def quote_atom( str )
# If the string supplied has ATOM unsafe characters in it, will return the string quoted
# in double quotes, otherwise returns the string unmodified
(ATOM_UNSAFE === str) ? dquote(str) : str
end

# If the string supplied has PHRASE unsafe characters in it, will return the string quoted
# in double quotes, otherwise returns the string unmodified
def quote_phrase( str )
# If the string supplied has PHRASE unsafe characters in it, will return the string quoted
# in double quotes, otherwise returns the string unmodified
(PHRASE_UNSAFE === str) ? dquote(str) : str
end

# Returns true if the string supplied is free from characters not allowed as a TOKEN
def token_safe?( str )
# Returns true if the string supplied is free from characters not allowed as a TOKEN
not TOKEN_UNSAFE === str
end

# If the string supplied has TOKEN unsafe characters in it, will return the string quoted
# in double quotes, otherwise returns the string unmodified
def quote_token( str )
# If the string supplied has TOKEN unsafe characters in it, will return the string quoted
# in double quotes, otherwise returns the string unmodified
(TOKEN_UNSAFE === str) ? dquote(str) : str
end

def dquote( str )
# Wraps supplied string in double quotes unless it is already wrapped
# Returns double quoted string
# Wraps supplied string in double quotes unless it is already wrapped
# Returns double quoted string
def dquote( str ) #:nodoc:
unless str =~ /^".*?"$/
'"' + str.gsub(/["\\]/n) {|s| '\\' + s } + '"'
else
Expand All @@ -127,12 +158,14 @@ def dquote( str )
end
private :dquote

# Unwraps supplied string from inside double quotes
# Returns unquoted string
def unquote( str )
# Unwraps supplied string from inside double quotes
# Returns unquoted string
str =~ /^"(.*?)"$/ ? $1 : str
end

# Provides a method to join a domain name by it's parts and also makes it
# ATOM safe by quoting it as needed
def join_domain( arr )
arr.map {|i|
if /\A\[.*\]\z/ === i
Expand All @@ -143,7 +176,7 @@ def join_domain( arr )
}.join('.')
end


#:stopdoc:
ZONESTR_TABLE = {
'jst' => 9 * 60,
'eet' => 2 * 60,
Expand Down Expand Up @@ -189,9 +222,10 @@ def join_domain( arr )
'y' => 12 * 60,
'z' => 0 * 60
}
#:startdoc:

# Takes a time zone string from an EMail and converts it to Unix Time (seconds)
def timezone_string_to_unixtime( str )
# Takes a time zone string from an EMail and converts it to Unix Time (seconds)
if m = /([\+\-])(\d\d?)(\d\d)/.match(str)
sec = (m[2].to_i * 60 + m[3].to_i) * 60
m[1] == '-' ? -sec : sec
Expand All @@ -202,7 +236,7 @@ def timezone_string_to_unixtime( str )
end
end


#:stopdoc:
WDAY = %w( Sun Mon Tue Wed Thu Fri Sat TMailBUG )
MONTH = %w( TMailBUG Jan Feb Mar Apr May Jun
Jul Aug Sep Oct Nov Dec TMailBUG )
Expand All @@ -222,7 +256,7 @@ def time2str( tm )


MESSAGE_ID = /<[^\@>]+\@[^>\@]+>/

def message_id?( str )
MESSAGE_ID === str
end
Expand Down Expand Up @@ -295,6 +329,8 @@ def quote_boundary
end
end
end
#:startdoc:


end

Expand Down

0 comments on commit 9680049

Please sign in to comment.