Class: Mail::Field

Inherits:
Object show all
Includes:
Comparable, Utilities
Defined in:
lib/mail/field.rb

Overview

Provides a single class to call to create a new structured or unstructured field. Works out per RFC what field of field it is being given and returns the correct field of class back on new.

===Per RFC 2822

2.2. Header Fields

Header fields are lines composed of a field name, followed by a colon
(":"), followed by a field body, and terminated by CRLF.  A field
name MUST be composed of printable US-ASCII characters (i.e.,
characters that have values between 33 and 126, inclusive), except
colon.  A field body may be composed of any US-ASCII characters,
except for CR and LF.  However, a field body may contain CRLF when
used in header "folding" and  "unfolding" as described in section
2.2.3.  All field bodies MUST conform to the syntax described in
sections 3 and 4 of this standard.

Defined Under Namespace

Classes: FieldError, ParseError, SyntaxError

Constant Summary collapse

STRUCTURED_FIELDS =
%w[ bcc cc content-description content-disposition
content-id content-location content-transfer-encoding
content-type date from in-reply-to keywords message-id
mime-version received references reply-to
resent-bcc resent-cc resent-date resent-from
resent-message-id resent-sender resent-to
return-path sender to ]
KNOWN_FIELDS =
STRUCTURED_FIELDS + ['comments', 'subject']
FIELDS_MAP =
{
  "to" => ToField,
  "cc" => CcField,
  "bcc" => BccField,
  "message-id" => MessageIdField,
  "in-reply-to" => InReplyToField,
  "references" => ReferencesField,
  "subject" => SubjectField,
  "comments" => CommentsField,
  "keywords" => KeywordsField,
  "date" => DateField,
  "from" => FromField,
  "sender" => SenderField,
  "reply-to" => ReplyToField,
  "resent-date" => ResentDateField,
  "resent-from" => ResentFromField,
  "resent-sender" =>  ResentSenderField,
  "resent-to" => ResentToField,
  "resent-cc" => ResentCcField,
  "resent-bcc" => ResentBccField,
  "resent-message-id" => ResentMessageIdField,
  "return-path" => ReturnPathField,
  "received" => ReceivedField,
  "mime-version" => MimeVersionField,
  "content-transfer-encoding" => ContentTransferEncodingField,
  "content-description" => ContentDescriptionField,
  "content-disposition" => ContentDispositionField,
  "content-type" => ContentTypeField,
  "content-id" => ContentIdField,
  "content-location" => ContentLocationField,
}
FIELD_NAME_MAP =
FIELDS_MAP.inject({}) do |map, (field, field_klass)|
  map.update(field => field_klass::CAPITALIZED_FIELD)
end
FIELD_ORDER =
%w[ return-path received
resent-date resent-from resent-sender resent-to
resent-cc resent-bcc resent-message-id
date from sender reply-to to cc bcc
message-id in-reply-to references
subject comments keywords
mime-version content-type content-transfer-encoding
content-location content-disposition content-description ]
FIELD_ORDER_LOOKUP =

Constants included from Patterns

Patterns::ATOM_UNSAFE, Patterns::CONTROL_CHAR, Patterns::CRLF, Patterns::FIELD_BODY, Patterns::FIELD_LINE, Patterns::FIELD_NAME, Patterns::FIELD_PREFIX, Patterns::FIELD_SPLIT, Patterns::FWS, Patterns::HEADER_LINE, Patterns::HEADER_SPLIT, Patterns::PHRASE_UNSAFE, Patterns::QP_SAFE, Patterns::QP_UNSAFE, Patterns::TEXT, Patterns::TOKEN_UNSAFE, Patterns::WSP

Instance Method Summary collapse

Methods included from Utilities

#atom_safe?, #bracket, #capitalize_field, #constantize, #dasherize, #dquote, #escape_paren, #map_lines, #map_with_index, #match_to_s, #paren, #quote_atom, #quote_phrase, #quote_token, #token_safe?, #unbracket, #underscoreize, #unparen, #unquote, #uri_escape, #uri_parser, #uri_unescape

Constructor Details

#initialize(name, value = nil, charset = 'utf-8') ⇒ Field

Accepts a string:

Field.new("field-name: field data")

Or name, value pair:

Field.new("field-name", "value")

Or a name by itself:

Field.new("field-name")

Note, does not want a terminating carriage return. Returns self appropriately parsed. If value is not a string, then it will be passed through as is, for example, content-type field can accept an array with the type and a hash of parameters:

Field.new('content-type', ['text', 'plain', => 'UTF-8'])



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/mail/field.rb', line 114

def initialize(name, value = nil, charset = 'utf-8')
  case
  when name =~ /:/                  # Field.new("field-name: field data")
    @charset = value.blank? ? charset : value
    @name = name[FIELD_PREFIX]
    @raw_value = name
    @value = nil
  when name !~ /:/ && value.blank?  # Field.new("field-name")
    @name = name
    @value = nil
    @raw_value = nil
    @charset = charset
  else                              # Field.new("field-name", "value")
    @name = name
    @value = value
    @raw_value = nil
    @charset = charset
  end
  @name = FIELD_NAME_MAP[@name.to_s.downcase] || @name
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



188
189
190
# File 'lib/mail/field.rb', line 188

def method_missing(name, *args, &block)
  field.send(name, *args, &block)
end

Instance Method Details

#<=>(other) ⇒ Object



180
181
182
# File 'lib/mail/field.rb', line 180

def <=>( other )
  self.field_order_id <=> other.field_order_id
end

#fieldObject



139
140
141
142
# File 'lib/mail/field.rb', line 139

def field
  _, @value = split(@raw_value) if @raw_value && !@value
  @field ||= create_field(@name, @value, @charset)
end

#field=(value) ⇒ Object



135
136
137
# File 'lib/mail/field.rb', line 135

def field=(value)
  @field = value
end

#field_order_idObject



184
185
186
# File 'lib/mail/field.rb', line 184

def field_order_id
  @field_order_id ||= (FIELD_ORDER_LOOKUP[self.name.to_s.downcase] || 100)
end

#inspectObject



160
161
162
163
164
# File 'lib/mail/field.rb', line 160

def inspect
  "#<#{self.class.name} 0x#{(object_id * 2).to_s(16)} #{instance_variables.map do |ivar|
    "#{ivar}=#{instance_variable_get(ivar).inspect}"
  end.join(" ")}>"
end

#nameObject



144
145
146
# File 'lib/mail/field.rb', line 144

def name
  @name
end

#responsible_for?(val) ⇒ Boolean

Returns:

  • (Boolean)


174
175
176
# File 'lib/mail/field.rb', line 174

def responsible_for?( val )
  name.to_s.casecmp(val.to_s) == 0
end

#same(other) ⇒ Object Also known as: ==



170
171
172
# File 'lib/mail/field.rb', line 170

def same( other )
  match_to_s(other.name, self.name)
end

#to_sObject



156
157
158
# File 'lib/mail/field.rb', line 156

def to_s
  field.to_s
end

#update(name, value) ⇒ Object



166
167
168
# File 'lib/mail/field.rb', line 166

def update(name, value)
  @field = create_field(name, value, @charset)
end

#valueObject



148
149
150
# File 'lib/mail/field.rb', line 148

def value
  field.value
end

#value=(val) ⇒ Object



152
153
154
# File 'lib/mail/field.rb', line 152

def value=(val)
  @field = create_field(name, val, @charset)
end