Class: Ronin::Support::Network::EmailAddress

Inherits:
Object
  • Object
show all
Defined in:
lib/ronin/support/network/email_address.rb

Overview

Represents an email address.

Features

Examples

Builds a new email address:

email = EmailAddress.new(mailbox: 'john.smith', domain: 'example.com')

Parses an email address:

email = EmailAddress.parse("John Smith <john.smith@example.com>")
# => #<Ronin::Support::Network::EmailAddress:0x00007f49586d6a20
      @address=nil,
      @domain="example.com",
      @mailbox="john.smith",
      @name="John Smith",
      @routing=nil,
      @tag=nil>

Deobfuscate an obfuscated email address:

EmailAddress.deobfuscate("john[dot]smith [at] example[dot]com")
# => "john.smith@example.com"

Obfuscate an email address:

email = EmailAddress.parse("john.smith@example.com")
email.obfuscate
# => "john <dot> smith <at> example <dot> com"

Get every obfuscation of an email address:

 email.obfuscations
 # => ["john.smith AT example.com",
 #     "john.smith at example.com",
 #     "john.smith[AT]example.com",
 #     "john.smith[at]example.com",
 #     "john.smith [AT] example.com",
 #     "john.smith [at] example.com",
 #     "john.smith<AT>example.com",
 #     "john.smith<at>example.com",
 #     "john.smith <AT> example.com",
 #     "john.smith <at> example.com",
 #     "john.smith{AT}example.com",
 #     "john.smith{at}example.com",
 #     "john.smith {AT} example.com",
 #     "john.smith {at} example.com",
 #     "john.smith(AT)example.com",
 #     "john.smith(at)example.com",
 #     "john.smith (AT) example.com",
 #     "john.smith (at) example.com",
 #     "john DOT smith AT example DOT com",
 #     "john dot smith at example dot com",
 #     "john[DOT]smith[AT]example[DOT]com",
 #     "john[dot]smith[at]example[dot]com",
 #     "john [DOT] smith [AT] example [DOT] com",
 #     "john [dot] smith [at] example [dot] com",
 #     "john<DOT>smith<AT>example<DOT>com",
 #     "john<dot>smith<at>example<dot>com",
 #     "john <DOT> smith <AT> example <DOT> com",
 #     "john <dot> smith <at> example <dot> com",
 #     "john{DOT}smith{AT}example{DOT}com",
 #     "john{dot}smith{at}example{dot}com",
 #     "john {DOT} smith {AT} example {DOT} com",
 #     "john {dot} smith {at} example {dot} com",
 #     "john(DOT)smith(AT)example(DOT)com",
 #     "john(dot)smith(at)example(dot)com",
 #     "john (DOT) smith (AT) example (DOT) com",
 #     "john (dot) smith (at) example (dot) com"]

Obfuscation Methods collapse

OBFUSCATIONS =

Email address obfuscation rules.

Since:

  • 1.0.0

[
  [/\@/, {'@' => ' @ '   }],
  [/\@/, {'@' => ' AT '  }],
  [/\@/, {'@' => ' at '  }],
  [/\@/, {'@' => '[AT]'  }],
  [/\@/, {'@' => '[at]'  }],
  [/\@/, {'@' => ' [AT] '}],
  [/\@/, {'@' => ' [at] '}],
  [/\@/, {'@' => '<AT>'  }],
  [/\@/, {'@' => '<at>'  }],
  [/\@/, {'@' => ' <AT> '}],
  [/\@/, {'@' => ' <at> '}],
  [/\@/, {'@' => '{AT}'  }],
  [/\@/, {'@' => '{at}'  }],
  [/\@/, {'@' => ' {AT} '}],
  [/\@/, {'@' => ' {at} '}],
  [/\@/, {'@' => '(AT)'  }],
  [/\@/, {'@' => '(at)'  }],
  [/\@/, {'@' => ' (AT) '}],
  [/\@/, {'@' => ' (at) '}],
  [/[\.\@]/, {'.' => ' DOT ',   '@' => ' AT '  }],
  [/[\.\@]/, {'.' => ' dot ',   '@' => ' at '  }],
  [/[\.\@]/, {'.' => '[DOT]',   '@' => '[AT]'  }],
  [/[\.\@]/, {'.' => '[dot]',   '@' => '[at]'  }],
  [/[\.\@]/, {'.' => ' [DOT] ', '@' => ' [AT] '}],
  [/[\.\@]/, {'.' => ' [dot] ', '@' => ' [at] '}],
  [/[\.\@]/, {'.' => '<DOT>',   '@' => '<AT>'  }],
  [/[\.\@]/, {'.' => '<dot>',   '@' => '<at>'  }],
  [/[\.\@]/, {'.' => ' <DOT> ', '@' => ' <AT> '}],
  [/[\.\@]/, {'.' => ' <dot> ', '@' => ' <at> '}],
  [/[\.\@]/, {'.' => '{DOT}',   '@' => '{AT}'  }],
  [/[\.\@]/, {'.' => '{dot}',   '@' => '{at}'  }],
  [/[\.\@]/, {'.' => ' {DOT} ', '@' => ' {AT} '}],
  [/[\.\@]/, {'.' => ' {dot} ', '@' => ' {at} '}],
  [/[\.\@]/, {'.' => '(DOT)',   '@' => '(AT)'  }],
  [/[\.\@]/, {'.' => '(dot)',   '@' => '(at)'  }],
  [/[\.\@]/, {'.' => ' (DOT) ', '@' => ' (AT) '}],
  [/[\.\@]/, {'.' => ' (dot) ', '@' => ' (at) '}]
]

Constant Summary collapse

DEOBFUSCATIONS =

Email address de-obfuscation rules.

Since:

  • 1.0.0

{
  /\s+@\s+/                 => '@',
  /\s+(?:at|AT)\s+/         => '@',
  /\s+(?:dot|DOT)\s+/       => '.',
  /\s*\[(?:at|AT)\]\s*/     => '@',
  /\s*\[(?:dot|DOT)\]\s*/   => '.',
  /\s*\<(?:at|AT)\>\s*/     => '@',
  /\s*\<(?:dot|DOT)\>\s*/   => '.',
  /\s*\{(?:at|AT)\}\s*/     => '@',
  /\s*\{(?:dot|DOT)\}\s*/   => '.',
  /\s*\((?:at|AT)\)\s*/     => '@',
  /\s*\((?:dot|DOT)\)\s*/   => '.'
}

Instance Attribute Summary collapse

Obfuscation Methods collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name: nil, mailbox:, tag: nil, routing: nil, domain: nil, address: nil) ⇒ EmailAddress

Initializes the email address.

Examples:

Initializing a basic email address.

email = EmailAddress.new(mailbox: 'john.smith', domain: 'example.com')

Initializing an email address with a name:

email = EmailAddress.new(name: 'John Smith', mailbox: 'john.smith', domain: 'example.com')

Initializing an email address with a sorting tag:

email = EmailAddress.new(mailbox: 'john.smith', tag: 'spam', domain: 'example.com')

Parameters:

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

    The optional name associated with the email address (ex: John Smith <john.smith@example.com).

  • mailbox (String)

    The mailbox or username of the email address.

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

    The optional sorting tag of the email address (ex: john.smith+tag@example.com).

  • routing (Array<String>, nil) (defaults to: nil)

    Additional hosts to route sent emails through; aka the "percent hack" (ex: john.smith%host3.com%host2.com@host1.com).

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

    The domain of the email address (ex: john.smith@example.com).

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

    The IP address of the email address (ex: john.smith@[1.2.3.4]).

Raises:

  • (ArgumentError)

    Must specify either the domain: or address: keyword arguments.

Since:

  • 1.0.0



180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/ronin/support/network/email_address.rb', line 180

def initialize(name: nil, mailbox: , tag: nil, routing: nil, domain: nil, address: nil)
  @name    = name
  @mailbox = mailbox
  @tag     = tag
  @routing = routing

  unless (domain.nil? ^ address.nil?)
    raise(ArgumentError,"must specify domain: or address: keyword arguments")
  end

  @domain  = domain
  @address = address
end

Instance Attribute Details

#addressString? (readonly)

The IP address of the email address (ex: john.smith@[1.2.3.4]).

Returns:

Since:

  • 1.0.0



142
143
144
# File 'lib/ronin/support/network/email_address.rb', line 142

def address
  @address
end

#domainString? (readonly)

The domain of the email address (ex: john.smith@example.com).

Returns:

Since:

  • 1.0.0



137
138
139
# File 'lib/ronin/support/network/email_address.rb', line 137

def domain
  @domain
end

#mailboxString (readonly) Also known as: username

The mailbox or username of the email address.

Returns:

Since:

  • 1.0.0



118
119
120
# File 'lib/ronin/support/network/email_address.rb', line 118

def mailbox
  @mailbox
end

#nameString? (readonly)

The optional name associated with the email address (ex: John Smith <john.smith@example.com).

Returns:

Since:

  • 1.0.0



113
114
115
# File 'lib/ronin/support/network/email_address.rb', line 113

def name
  @name
end

#routingArray<String>? (readonly)

Additional hosts to route sent emails through; aka the "percent hack" (ex: john.smith%host3.com%host2.com@host1.com).

Returns:

Since:

  • 1.0.0



132
133
134
# File 'lib/ronin/support/network/email_address.rb', line 132

def routing
  @routing
end

#tagString? (readonly)

The optional sorting tag of the email address (ex: john.smith+tag@example.com).

Returns:

Since:

  • 1.0.0



126
127
128
# File 'lib/ronin/support/network/email_address.rb', line 126

def tag
  @tag
end

Class Method Details

.deobfuscate(string) ⇒ String

Deobfuscates an obfuscated email address.

Examples:

EmailAddress.deobfuscate("john[dot]smith [at] example[dot]com")
# => "john.smith@example.com"

Parameters:

  • string (String)

    The obfuscated email address to deobfuscate.

Returns:

  • (String)

    The deobfuscated email address.

Since:

  • 1.0.0



355
356
357
358
359
360
361
# File 'lib/ronin/support/network/email_address.rb', line 355

def self.deobfuscate(string)
  DEOBFUSCATIONS.each do |pattern,replace|
    string = string.gsub(pattern,replace)
  end

  return string
end

.parse(string) ⇒ EmailAddress

Parses an email address.

Examples:

email = EmailAddress.parse("John Smith <john.smith@example.com>")
# => #<Ronin::Support::Network::EmailAddress:0x00007f49586d6a20
      @address=nil,
      @domain="example.com",
      @mailbox="john.smith",
      @name="John Smith",
      @routing=nil,
      @tag=nil>

Parameters:

  • string (String)

    The email string to parse.

Returns:

Raises:

See Also:

Since:

  • 1.0.0



218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/ronin/support/network/email_address.rb', line 218

def self.parse(string)
  if string.include?('<') && string.end_with?('>')
    # Name <local-part@domain.com>
    if (match = string.match(/^([^<]+)\s+<([^>]+)>$/))
      name    = match[1]
      address = match[2]
    else
      raise(InvalidEmailAddress,"invalid email address: #{string.inspect}")
    end
  else
    name    = nil
    address = string
  end

  return new(name: name, **parse_address(address))
end

.parse_address(string) ⇒ Hash{Symbol => Object}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parses the address portion of an email address.

Parameters:

  • string (String)

    the email address string to parse.

Returns:

  • (Hash{Symbol => Object})

    Keyword arguments for #initialize.

Raises:

Since:

  • 1.0.0



249
250
251
252
253
254
255
256
257
258
# File 'lib/ronin/support/network/email_address.rb', line 249

def self.parse_address(string)
  unless string.include?('@')
    raise(InvalidEmailAddress,"invalid email address: #{string.inspect}")
  end

  # local-part@domain.com
  local_part, domain = string.split('@',2)

  return {**parse_local_part(local_part), **parse_domain(domain)}
end

.parse_domain(string) ⇒ Hash{Symbol => Object}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parses the domain portion of an email address.

Parameters:

  • string (String)

    The domain portion to parse.

Returns:

  • (Hash{Symbol => Object})

    Keyword arguments for #initialize.

Since:

  • 1.0.0



313
314
315
316
317
318
319
320
321
322
323
324
325
# File 'lib/ronin/support/network/email_address.rb', line 313

def self.parse_domain(string)
  domain  = nil
  address = nil

  # extract IP addresses from the domain part (ex: `user@[1.2.3.4]`)
  if string.start_with?('[') && string.end_with?(']')
    address = string[1..-2]
  else
    domain  = string
  end

  return {domain: domain, address: address}
end

.parse_local_part(string) ⇒ Hash{Symbol => Object}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parses the local-part portion of an email address.

Parameters:

  • string (String)

    the local-part string to parse.

Returns:

  • (Hash{Symbol => Object})

    Keyword arguments for #initialize.

Since:

  • 1.0.0



271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/ronin/support/network/email_address.rb', line 271

def self.parse_local_part(string)
  routing = nil

  if string.include?('%')
    mailbox, *routing = string.split('%')
  else
    mailbox = string
    routing = nil
  end

  return {routing: routing, **parse_mailbox(mailbox)}
end

.parse_mailbox(string) ⇒ Hash{Symbol => Object}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parses the mailbox portion of an email address.

Parameters:

  • string (String)

    The mailbox string to parse.

Returns:

  • (Hash{Symbol => Object})

    Keyword arguments for #initialize.

Since:

  • 1.0.0



295
296
297
298
299
300
# File 'lib/ronin/support/network/email_address.rb', line 295

def self.parse_mailbox(string)
  # extract any sorting-tags (ex: `user+service@domain.com`)
  mailbox, tag = string.split('+',2)

  return {mailbox: mailbox, tag: tag}
end

Instance Method Details

#each_obfuscation {|obfuscated| ... } ⇒ Enumerator

Enumerates over each obfuscation of the email address.

Examples:

email = EmailAddress.parse("john.smith@example.com")
email.each_obfuscation { |obfuscated_email| ... }

Yields:

  • (obfuscated)

    If a block is given, it will be passed every obfuscation of the email address.

Yield Parameters:

  • obfuscated (String)

    An obfuscated version of the email address.

Returns:

  • (Enumerator)

    If no block is given, an Enumerator will be returned.

See Also:

Since:

  • 1.0.0



503
504
505
506
507
508
509
510
511
512
513
# File 'lib/ronin/support/network/email_address.rb', line 503

def each_obfuscation
  return enum_for(__method__) unless block_given?

  string = to_s

  OBFUSCATIONS.each do |gsub_args|
    yield string.gsub(*gsub_args)
  end

  return nil
end

#hostnameString

The hostname to connect to.

Returns:

Since:

  • 1.0.0



389
390
391
# File 'lib/ronin/support/network/email_address.rb', line 389

def hostname
  @domain || @address
end

#normalizeEmailAddress

Creates a new email address without the #tag or #routing attribute.

Examples:

email = EmailAddress.parse("John Smith <john.smith+spam@example.com>")
email.normalize.to_s
# => "john.smith@example.com"

Returns:

  • (EmailAddress)

    The new normalized email address object.

Since:

  • 1.0.0



375
376
377
378
379
380
381
# File 'lib/ronin/support/network/email_address.rb', line 375

def normalize
  EmailAddress.new(
    mailbox: mailbox,
    domain:  domain,
    address: address
  )
end

#obfuscateString

Obfuscates the email address.

Examples:

email = EmailAddress.parse("john.smith@example.com")
email.obfuscate
# => "john.smith [AT] example.com"
email.obfuscate
# => "john <dot> smith <at> example <dot> com"

Returns:

  • (String)

    A randomly obfuscated version of the email address.

See Also:

Since:

  • 1.0.0



478
479
480
481
482
# File 'lib/ronin/support/network/email_address.rb', line 478

def obfuscate
  string = to_s
  string.gsub!(*OBFUSCATIONS.sample)
  return string
end

#obfuscationsArray<String>

Returns every obfuscation of the email address.

Examples:

email = EmailAddress.parse("john.smith@example.com")
email.obfuscations
# => ["john.smith AT example.com",
#     "john.smith at example.com",
#     "john.smith[AT]example.com",
#     "john.smith[at]example.com",
#     "john.smith [AT] example.com",
#     "john.smith [at] example.com",
#     "john.smith<AT>example.com",
#     "john.smith<at>example.com",
#     "john.smith <AT> example.com",
#     "john.smith <at> example.com",
#     "john.smith{AT}example.com",
#     "john.smith{at}example.com",
#     "john.smith {AT} example.com",
#     "john.smith {at} example.com",
#     "john.smith(AT)example.com",
#     "john.smith(at)example.com",
#     "john.smith (AT) example.com",
#     "john.smith (at) example.com",
#     "john DOT smith AT example DOT com",
#     "john dot smith at example dot com",
#     "john[DOT]smith[AT]example[DOT]com",
#     "john[dot]smith[at]example[dot]com",
#     "john [DOT] smith [AT] example [DOT] com",
#     "john [dot] smith [at] example [dot] com",
#     "john<DOT>smith<AT>example<DOT>com",
#     "john<dot>smith<at>example<dot>com",
#     "john <DOT> smith <AT> example <DOT> com",
#     "john <dot> smith <at> example <dot> com",
#     "john{DOT}smith{AT}example{DOT}com",
#     "john{dot}smith{at}example{dot}com",
#     "john {DOT} smith {AT} example {DOT} com",
#     "john {dot} smith {at} example {dot} com",
#     "john(DOT)smith(AT)example(DOT)com",
#     "john(dot)smith(at)example(dot)com",
#     "john (DOT) smith (AT) example (DOT) com",
#     "john (dot) smith (at) example (dot) com"]

Returns:

  • (Array<String>)

    The Array containing every obfuscation of the email address.

See Also:

Since:

  • 1.0.0



563
564
565
# File 'lib/ronin/support/network/email_address.rb', line 563

def obfuscations
  each_obfuscation.to_a
end

#to_sString Also known as: to_str

Converts the email address back into a string.

Examples:

email = EmailAddress.parse("John Smith <john.smith+spam@example.com>")
email.to_s
# => "John Smith <john.smith+spam@example.com>"

Returns:

  • (String)

    The string representation of the email address.

Since:

  • 1.0.0



404
405
406
407
408
409
410
411
412
413
414
# File 'lib/ronin/support/network/email_address.rb', line 404

def to_s
  string = "#{@mailbox}"
  string << "+#{@tag}"               if @tag
  string << "%#{@routing.join('%')}" if @routing
  string << "@"
  string << if @address then "[#{@address}]"
            else             @domain
            end
  string = "#{@name} <#{string}>" if @name
  return string
end