Email Spoofing

Emails are sent via the Simple Mail Transfer Protocol. SMTP does not have a mechanism for authentication, so malicious actors often send emails using a spoofed “from” address to mislead the recipient about the sender of the message.

A common method of attack is “phishing” - sending emails that attempt to trick a user into sharing their login credentials. Phishing emails will often warn a user that somebody has tried to access their account, and suggest they change their password immediately.

However, the “password change” link will take the user to a malicious site owned by the phisher - but one that looks completely authentic.

Your user will be asked to enter their old authentication details - which will be saved off to a database of stolen passwords.

Then the site will then redirect to the legitimate password reset page for your site, so the user does not suspect anything.

Protecting against phishing emails is largely in the hands of the email service provider. Email service providers spend a great deal of resources trying to detect spam and malicious emails - you can help them protect your users in a couple of ways.

By changing your DNS records to list a Sender Policy Framework (SPF), you can explicitly state which servers are allowed to send email from your domain. This will help flag spoofed emails sent by malicious actors.

By implementing Domain Key Identified Mail (DKIM), you can prove that an email was legitimately sent from your domain, and that it wasn’t modified in transit.

DKIM adds a digital signature to the email header. The mail receiving program will recalculate the signature on receipt to verify the mail is authentic and has not been tampered with.

Edit the email below and watch how the DKIM signature changes.

Let’s see how to implement these protective measures.

Please re-enter your password
Sign in
Password incorrect!
Sign in
Password harvesting started...
# @return [DkimHeader] Constructed signature for the mail message
def dkim_header
  dkim_header =

  raise "A private key is required" unless private_key
  raise "A domain is required"      unless domain
  raise "A selector is required"    unless selector

  # Add basic DKIM info
  dkim_header['v'] = '1'
  dkim_header['a'] = signing_algorithm
  dkim_header['c'] = "#{header_canon}/#{body_canon}"
  dkim_header['d'] = domain
  dkim_header['i'] = identity if identity
  dkim_header['q'] = 'dns/txt'
  dkim_header['s'] = selector
  dkim_header['t'] = (time ||

  # Add body hash and blank signature
  dkim_header['bh']= digest_alg.digest(canonical_body)
  dkim_header['h'] = signed_headers.join(':')
  dkim_header['b'] = ''

  # Calculate signature based on intermediate signature header
  headers = canonical_header
  headers << dkim_header.to_s(header_canonicalization)
  dkim_header['b'] = private_key.sign(digest_alg, headers)

An implementation of the DKIM signature algorithm in Ruby.
New Message
SMTP Envelope
Mr Friendly <>
Quick question
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; q=dns/txt; s=dkim; bh=01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b; h=from:subject:to:content-type; b=FzZNv/CLejBrRm+Mba/DtI2XNyv6+PdZBLTZXgLcJcPDayAO3SmG16aQZEHY+UPIsPDydFKty OwOroWkeKqHqOuOWDc4nFt6lRLUIg09QRsGQ2aeVCZA5lmQvx9c0cFmvWF/H02KeFTHDI9/Brx+ RxA1U4oR4XSsMxZ8sDTRLqM=?YAlYATAdGxjXMXHGM5l/WcY5Jb6T7f4DdMjrOQc1aoiiZb078M XOmgwxHDe1yhJs1mHN/PhVa3/z3l4/OByK4IzUZ73jWF+Owxw6vCvB2pgvnVApREAcMsMfgtEn3 A5rrf15nkyZxLizeNc/dinVzQKfBzIw4zIzdLXzpwfleYQG53kmh9nc6TbeJVEkYhIf6+i7Z/s/ qJY9cJzG2VTJr/kvJ9ufAgjyE1D9jm1BXhwpklYkjnxgaqnC4dHXXf8rvvRHydo8dtPNl55xdqb J0BIwCqdAd1AS4tdo4bHP6dboGeOwifasJfR6wts5Sd3aKr6YNBUYtT70wA6n8Ok/kgbx6fpcOM 4FBGcwF0OUz6M9by1h5S+GeRaj2q1DQRCQV735UUHUuyfMP8dUSFwMsmKCmsnapm+Ffvkjjp7BU JdpWoZz2K+VGxsDBsBeQWvVL4O95mnvcr1NWD1awTe/5sPD40SDYTNqa5z8kGeaq6i0AUpyCL0p 8F8bIBQc9g/zIkZ7vKH6jLsTO0pvg44MvuH+gHXD5EUivVTHh7ZTt7BbK/0yKBhd5ClOnUCxxEK 4r335PcH12Cg6YdVyPEcvuYhUWxYZROUIL4YkMMO4/lmDQJW6turahMybMDi0lVxf0sahvGkxMG 0+gAaXCpDEIQ==