~mark-mims/ubuntu/oneiric/ruby-actionmailer-2.3/fix-2.3.14

« back to all changes in this revision

Viewing changes to lib/action_mailer/vendor/tmail-1.2.7/tmail/address.rb

  • Committer: Bazaar Package Importer
  • Author(s): Ondřej Surý
  • Date: 2011-06-01 16:49:50 UTC
  • Revision ID: james.westby@ubuntu.com-20110601164950-zd4413lamwzyln51
Tags: upstream-2.3.11
Import upstream version 2.3.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
=begin rdoc
 
2
 
 
3
= Address handling class
 
4
 
 
5
=end
 
6
#--
 
7
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
 
8
#
 
9
# Permission is hereby granted, free of charge, to any person obtaining
 
10
# a copy of this software and associated documentation files (the
 
11
# "Software"), to deal in the Software without restriction, including
 
12
# without limitation the rights to use, copy, modify, merge, publish,
 
13
# distribute, sublicense, and/or sell copies of the Software, and to
 
14
# permit persons to whom the Software is furnished to do so, subject to
 
15
# the following conditions:
 
16
#
 
17
# The above copyright notice and this permission notice shall be
 
18
# included in all copies or substantial portions of the Software.
 
19
#
 
20
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
21
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
22
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
23
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 
24
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 
25
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
26
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
27
#
 
28
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
 
29
# with permission of Minero Aoki.
 
30
#++
 
31
 
 
32
require 'tmail/encode'
 
33
require 'tmail/parser'
 
34
 
 
35
 
 
36
module TMail
 
37
 
 
38
  # = Class Address
 
39
  # 
 
40
  # Provides a complete handling library for email addresses. Can parse a string of an
 
41
  # address directly or take in preformatted addresses themselves.  Allows you to add
 
42
  # and remove phrases from the front of the address and provides a compare function for
 
43
  # email addresses.
 
44
  # 
 
45
  # == Parsing and Handling a Valid Address:
 
46
  # 
 
47
  # Just pass the email address in as a string to Address.parse:
 
48
  # 
 
49
  #  email = TMail::Address.parse('Mikel Lindsaar <mikel@lindsaar.net>')
 
50
  #  #=> #<TMail::Address mikel@lindsaar.net>
 
51
  #  email.address
 
52
  #  #=> "mikel@lindsaar.net"
 
53
  #  email.local
 
54
  #  #=> "mikel"
 
55
  #  email.domain
 
56
  #  #=> "lindsaar.net"
 
57
  #  email.name             # Aliased as phrase as well
 
58
  #  #=> "Mikel Lindsaar"
 
59
  # 
 
60
  # == Detecting an Invalid Address
 
61
  # 
 
62
  # If you want to check the syntactical validity of an email address, just pass it to
 
63
  # Address.parse and catch any SyntaxError:
 
64
  # 
 
65
  #  begin
 
66
  #    TMail::Address.parse("mikel   2@@@@@ me .com")
 
67
  #  rescue TMail::SyntaxError
 
68
  #    puts("Invalid Email Address Detected")
 
69
  #  else
 
70
  #    puts("Address is valid")
 
71
  #  end
 
72
  #  #=> "Invalid Email Address Detected"
 
73
  class Address
 
74
 
 
75
    include TextUtils #:nodoc:
 
76
    
 
77
    # Sometimes you need to parse an address, TMail can do it for you and provide you with
 
78
    # a fairly robust method of detecting a valid address.
 
79
    # 
 
80
    # Takes in a string, returns a TMail::Address object.
 
81
    # 
 
82
    # Raises a TMail::SyntaxError on invalid email format
 
83
    def Address.parse( str )
 
84
      Parser.parse :ADDRESS, str
 
85
    end
 
86
 
 
87
    def address_group? #:nodoc:
 
88
      false
 
89
    end
 
90
 
 
91
    # Address.new(local, domain)
 
92
    # 
 
93
    # Accepts:
 
94
    # 
 
95
    # * local - Left of the at symbol
 
96
    # 
 
97
    # * domain - Array of the domain split at the periods.
 
98
    # 
 
99
    # For example:
 
100
    # 
 
101
    #  Address.new("mikel", ["lindsaar", "net"])
 
102
    #  #=> "#<TMail::Address mikel@lindsaar.net>"
 
103
    def initialize( local, domain )
 
104
      if domain
 
105
        domain.each do |s|
 
106
          raise SyntaxError, 'empty word in domain' if s.empty?
 
107
        end
 
108
      end
 
109
      
 
110
      # This is to catch an unquoted "@" symbol in the local part of the
 
111
      # address.  Handles addresses like <"@"@me.com> and makes sure they
 
112
      # stay like <"@"@me.com> (previously were becoming <@@me.com>)
 
113
      if local && (local.join == '@' || local.join =~ /\A[^"].*?@.*?[^"]\Z/)
 
114
        @local = "\"#{local.join}\""
 
115
      else
 
116
        @local = local
 
117
      end
 
118
 
 
119
      @domain = domain
 
120
      @name   = nil
 
121
      @routes = []
 
122
    end
 
123
 
 
124
    # Provides the name or 'phrase' of the email address.
 
125
    # 
 
126
    # For Example:
 
127
    # 
 
128
    #  email = TMail::Address.parse("Mikel Lindsaar <mikel@lindsaar.net>")
 
129
    #  email.name
 
130
    #  #=> "Mikel Lindsaar"
 
131
    def name
 
132
      @name
 
133
    end
 
134
 
 
135
    # Setter method for the name or phrase of the email
 
136
    # 
 
137
    # For Example:
 
138
    # 
 
139
    #  email = TMail::Address.parse("mikel@lindsaar.net")
 
140
    #  email.name
 
141
    #  #=> nil
 
142
    #  email.name = "Mikel Lindsaar"
 
143
    #  email.to_s
 
144
    #  #=> "Mikel Lindsaar <mikel@me.com>"
 
145
    def name=( str )
 
146
      @name = str
 
147
      @name = nil if str and str.empty?
 
148
    end
 
149
 
 
150
    #:stopdoc:
 
151
    alias phrase  name
 
152
    alias phrase= name=
 
153
    #:startdoc:
 
154
    
 
155
    # This is still here from RFC 822, and is now obsolete per RFC2822 Section 4.
 
156
    # 
 
157
    # "When interpreting addresses, the route portion SHOULD be ignored."
 
158
    # 
 
159
    # It is still here, so you can access it.
 
160
    # 
 
161
    # Routes return the route portion at the front of the email address, if any.
 
162
    # 
 
163
    # For Example:
 
164
    #  email = TMail::Address.parse( "<@sa,@another:Mikel@me.com>")
 
165
    #  => #<TMail::Address Mikel@me.com>
 
166
    #  email.to_s
 
167
    #  => "<@sa,@another:Mikel@me.com>"
 
168
    #  email.routes
 
169
    #  => ["sa", "another"]
 
170
    def routes
 
171
      @routes
 
172
    end
 
173
    
 
174
    def inspect #:nodoc:
 
175
      "#<#{self.class} #{address()}>"
 
176
    end
 
177
 
 
178
    # Returns the local part of the email address
 
179
    # 
 
180
    # For Example:
 
181
    # 
 
182
    #  email = TMail::Address.parse("mikel@lindsaar.net")
 
183
    #  email.local
 
184
    #  #=> "mikel"
 
185
    def local
 
186
      return nil unless @local
 
187
      return '""' if @local.size == 1 and @local[0].empty?
 
188
      # Check to see if it is an array before trying to map it
 
189
      if @local.respond_to?(:map)
 
190
        @local.map {|i| quote_atom(i) }.join('.')
 
191
      else
 
192
        quote_atom(@local)
 
193
      end
 
194
    end
 
195
 
 
196
    # Returns the domain part of the email address
 
197
    # 
 
198
    # For Example:
 
199
    # 
 
200
    #  email = TMail::Address.parse("mikel@lindsaar.net")
 
201
    #  email.local
 
202
    #  #=> "lindsaar.net"
 
203
    def domain
 
204
      return nil unless @domain
 
205
      join_domain(@domain)
 
206
    end
 
207
 
 
208
    # Returns the full specific address itself
 
209
    # 
 
210
    # For Example:
 
211
    # 
 
212
    #  email = TMail::Address.parse("mikel@lindsaar.net")
 
213
    #  email.address
 
214
    #  #=> "mikel@lindsaar.net"
 
215
    def spec
 
216
      s = self.local
 
217
      d = self.domain
 
218
      if s and d
 
219
        s + '@' + d
 
220
      else
 
221
        s
 
222
      end
 
223
    end
 
224
 
 
225
    alias address spec
 
226
 
 
227
    # Provides == function to the email.  Only checks the actual address
 
228
    # and ignores the name/phrase component
 
229
    # 
 
230
    # For Example
 
231
    # 
 
232
    #  addr1 = TMail::Address.parse("My Address <mikel@lindsaar.net>")
 
233
    #  #=> "#<TMail::Address mikel@lindsaar.net>"
 
234
    #  addr2 = TMail::Address.parse("Another <mikel@lindsaar.net>")
 
235
    #  #=> "#<TMail::Address mikel@lindsaar.net>"
 
236
    #  addr1 == addr2
 
237
    #  #=> true
 
238
    def ==( other )
 
239
      other.respond_to? :spec and self.spec == other.spec
 
240
    end
 
241
 
 
242
    alias eql? ==
 
243
 
 
244
    # Provides a unique hash value for this record against the local and domain
 
245
    # parts, ignores the name/phrase value
 
246
    # 
 
247
    #  email = TMail::Address.parse("mikel@lindsaar.net")
 
248
    #  email.hash
 
249
    #  #=> 18767598
 
250
    def hash
 
251
      @local.hash ^ @domain.hash
 
252
    end
 
253
 
 
254
    # Duplicates a TMail::Address object returning the duplicate
 
255
    # 
 
256
    #  addr1 = TMail::Address.parse("mikel@lindsaar.net")
 
257
    #  addr2 = addr1.dup
 
258
    #  addr1.id == addr2.id
 
259
    #  #=> false
 
260
    def dup
 
261
      obj = self.class.new(@local.dup, @domain.dup)
 
262
      obj.name = @name.dup if @name
 
263
      obj.routes.replace @routes
 
264
      obj
 
265
    end
 
266
 
 
267
    include StrategyInterface #:nodoc:
 
268
 
 
269
    def accept( strategy, dummy1 = nil, dummy2 = nil ) #:nodoc:
 
270
      unless @local
 
271
        strategy.meta '<>'   # empty return-path
 
272
        return
 
273
      end
 
274
 
 
275
      spec_p = (not @name and @routes.empty?)
 
276
      if @name
 
277
        strategy.phrase @name
 
278
        strategy.space
 
279
      end
 
280
      tmp = spec_p ? '' : '<'
 
281
      unless @routes.empty?
 
282
        tmp << @routes.map {|i| '@' + i }.join(',') << ':'
 
283
      end
 
284
      tmp << self.spec
 
285
      tmp << '>' unless spec_p
 
286
      strategy.meta tmp
 
287
      strategy.lwsp ''
 
288
    end
 
289
 
 
290
  end
 
291
 
 
292
 
 
293
  class AddressGroup
 
294
 
 
295
    include Enumerable
 
296
 
 
297
    def address_group?
 
298
      true
 
299
    end
 
300
 
 
301
    def initialize( name, addrs )
 
302
      @name = name
 
303
      @addresses = addrs
 
304
    end
 
305
 
 
306
    attr_reader :name
 
307
    
 
308
    def ==( other )
 
309
      other.respond_to? :to_a and @addresses == other.to_a
 
310
    end
 
311
 
 
312
    alias eql? ==
 
313
 
 
314
    def hash
 
315
      map {|i| i.hash }.hash
 
316
    end
 
317
 
 
318
    def []( idx )
 
319
      @addresses[idx]
 
320
    end
 
321
 
 
322
    def size
 
323
      @addresses.size
 
324
    end
 
325
 
 
326
    def empty?
 
327
      @addresses.empty?
 
328
    end
 
329
 
 
330
    def each( &block )
 
331
      @addresses.each(&block)
 
332
    end
 
333
 
 
334
    def to_a
 
335
      @addresses.dup
 
336
    end
 
337
 
 
338
    alias to_ary to_a
 
339
 
 
340
    def include?( a )
 
341
      @addresses.include? a
 
342
    end
 
343
 
 
344
    def flatten
 
345
      set = []
 
346
      @addresses.each do |a|
 
347
        if a.respond_to? :flatten
 
348
          set.concat a.flatten
 
349
        else
 
350
          set.push a
 
351
        end
 
352
      end
 
353
      set
 
354
    end
 
355
 
 
356
    def each_address( &block )
 
357
      flatten.each(&block)
 
358
    end
 
359
 
 
360
    def add( a )
 
361
      @addresses.push a
 
362
    end
 
363
 
 
364
    alias push add
 
365
    
 
366
    def delete( a )
 
367
      @addresses.delete a
 
368
    end
 
369
 
 
370
    include StrategyInterface
 
371
 
 
372
    def accept( strategy, dummy1 = nil, dummy2 = nil )
 
373
      strategy.phrase @name
 
374
      strategy.meta ':'
 
375
      strategy.space
 
376
      first = true
 
377
      each do |mbox|
 
378
        if first
 
379
          first = false
 
380
        else
 
381
          strategy.puts_meta ','
 
382
        end
 
383
        strategy.space
 
384
        mbox.accept strategy
 
385
      end
 
386
      strategy.meta ';'
 
387
      strategy.lwsp ''
 
388
    end
 
389
 
 
390
  end
 
391
 
 
392
end   # module TMail