Class: Protege::Gateway::Mail::Address

Inherits:
Object
  • Object
show all
Defined in:
lib/protege/gateway/mail/address.rb

Overview

Value object representing an email address with optional plus-tag and optional display name.

Instances are frozen. Local part, tag, and domain are lowercased. Construct via .parse, which delegates lexical parsing to ::Mail::Address (handling RFC 5322 oddities like quoted display names and comments) and then layers plus-tag splitting and the routing-key concern on top.

Raises ArgumentError when input is nil, blank, or has no @ separator. Display name is excluded from equality — two addresses with the same local, tag, and domain are equal regardless of the surrounding display name.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(local:, domain:, tag: nil, display_name: nil) ⇒ Address

Wrap pre-parsed address parts and freeze. Prefer .parse.

Blank display names are coerced to nil so equality and rendering ignore them.

Parameters:

  • local (String)

    the bare mailbox name, lowercased.

  • domain (String)

    the domain, lowercased.

  • tag (String, nil) (defaults to: nil)

    the plus-tag, or nil.

  • display_name (String, nil) (defaults to: nil)

    the display name, or +nil+/blank to omit.



99
100
101
102
103
104
105
106
# File 'lib/protege/gateway/mail/address.rb', line 99

def initialize(local:, domain:, tag: nil, display_name: nil)
  @local        = local
  @tag          = tag
  @domain       = domain
  @display_name = display_name.nil? || display_name.to_s.strip.empty? ? nil : display_name

  freeze
end

Instance Attribute Details

#display_nameObject (readonly)

Display name from a "Name" <addr> form, or nil if absent.



35
36
37
# File 'lib/protege/gateway/mail/address.rb', line 35

def display_name
  @display_name
end

#domainObject (readonly)

Domain part of the address, lowercased.



32
33
34
# File 'lib/protege/gateway/mail/address.rb', line 32

def domain
  @domain
end

#localObject (readonly)

Bare mailbox name with any plus-tag stripped, lowercased.



26
27
28
# File 'lib/protege/gateway/mail/address.rb', line 26

def local
  @local
end

#tagObject (readonly)

Plus-tag suffix, or nil if no +tag was present in the source.



29
30
31
# File 'lib/protege/gateway/mail/address.rb', line 29

def tag
  @tag
end

Class Method Details

.parse(value) ⇒ Address

Parse a raw address string into a normalized Address.

Delegates the lexical parse to ::Mail::Address so quoted display names, comments, and other RFC 5322 syntax are handled, then splits any plus-tag off the local part and lowercases the local and domain.

Parameters:

  • value (String)

    the raw address (optionally with display name and plus-tag).

Returns:

  • (Address)

    the normalized, frozen address.

Raises:

  • (ArgumentError)

    when value is nil/blank or has no +@+-separated mailbox.



47
48
49
50
51
52
53
54
55
56
# File 'lib/protege/gateway/mail/address.rb', line 47

def parse(value)
  raise ArgumentError, 'address cannot be nil or blank' if value.nil? || value.to_s.strip.empty?

  parsed       = validate_mailbox(::Mail::Address.new(value.to_s.strip), value)
  local, tag   = split_plus_tag(parsed.local.downcase)
  domain       = parsed.domain.downcase
  display_name = parsed.display_name

  new(local:, tag:, domain:, display_name:)
end

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Compare for equality by local, tag, and domain, ignoring display name.

Parameters:

  • other (Object)

    the value to compare against.

Returns:

  • (Boolean)

    true when other is an Address with matching parts.



128
129
130
131
132
133
# File 'lib/protege/gateway/mail/address.rb', line 128

def ==(other)
  other.is_a?(Address) &&
    other.local == @local &&
    other.tag == @tag &&
    other.domain == @domain
end

#hashInteger

Hash by local, tag, and domain so equal addresses hash alike.

Returns:

  • (Integer)

    the hash code.



139
140
141
# File 'lib/protege/gateway/mail/address.rb', line 139

def hash
  [@local, @tag, @domain].hash
end

#routing_keyString

Return the tag-stripped local@domain form used for routing.

Returns:

  • (String)

    the routing key with no plus-tag.



111
112
113
# File 'lib/protege/gateway/mail/address.rb', line 111

def routing_key
  "#{@local}@#{@domain}"
end

#to_sString

Return the canonical mailbox form, including the plus-tag when present.

The display name is never included.

Returns:

  • (String)

    +local+tag@domain+ or local@domain.



120
121
122
# File 'lib/protege/gateway/mail/address.rb', line 120

def to_s
  @tag ? "#{@local}+#{@tag}@#{@domain}" : "#{@local}@#{@domain}"
end