Frequently Asked Questions

Emails are delivered on average in under 5 seconds. We operate in real-time, unlike other providers which rely upon delayed queues.

We do not write to disk or store logs – with the exception of errors and outbound SMTP (see our Privacy Policy).

Everything is done in-memory and our source code is on GitHub.

Estimated Setup Time: Less than 10 minutes
Enhanced Privacy Protection: If you would like to hide your information from being publicly searchable over the Internet, then please go to My Account Domains and upgrade your domain to a paid plan before starting this guide. Publicly searchable information on free plans includes, but is not limited to: aliases, forwarded addresses, recipients, and advanced settings such as custom port forwarding. If you would like to learn more about paid plans see our Pricing page – otherwise keep reading! All plans abide by our Privacy policy of strictly not storing metadata nor emails. We don't track you like other services do.
Getting Started: Carefully read and follow steps one through eight listed below. Be sure to replace the email address of user@gmail.com with the email address you want to forward emails to (if it isn't already accurate). Similarly be sure to replace example.com with your custom domain name (if it isn't already accurate).
  1. If you have already registered your domain name somewhere, then you must completely skip this step and go to step two! Otherwise you can click here to register your domain name.
  2. Do you remember where you registered your domain? Once you remember this, then follow the instructions below:
    Important: You must open a new tab and log in to your domain registrar. You can easily click on your "Registrar" below to automatically do this. In this new tab, you must navigate to the DNS management page at your registrar – and we have provided the step by step navigation steps below under the "Steps to Configure" column. Once you've navigated to this page in the new tab, you can return to this tab and proceed to step three below. Do not close the opened tab yet; you will need it for future steps!
    Registrar Steps to Configure
    1&1 Log in Domain Center (Select your domain) Edit DNS Settings
    Amazon Route 53 Log in Hosted Zones (Select your domain)
    Aplus.net Log in My Servers Domain Management DNS Manager
    Bluehost FOR ROCK: Log in Domains (Click the ▼ icon next to manage) DNS
    FOR LEGACY: Log in Domains Zone editor (Select your domain)
    Cloudflare Log in DNS
    DNS Made Easy Log in DNS (Select your domain)
    DNSimple Log in (Select your domain) DNS Manage
    Digital Ocean Log in Networking Domains (Select your domain) More Manage Domain
    Domain.com Log in In card view, click manage on your domain In list view, click the gear icon DNS & Nameservers DNS Records
    Domains.com
    Watch
    Log in (Select your domain) Manage (click gear icon) Click on DNS & Nameservers in left-hand menu
    DreamHost Log in Panel Domains Manage Domains DNS
    Dyn Log in Overview Manage Simple Editor Records
    Gandi Log in (Select your domain) Management Edit the zone
    GoDaddy
    Watch
    Log in Manage My Domains (Select your domain) Manage DNS
    Google Domains
    Watch
    Log in (Select your domain) Configure DNS
    Namecheap
    Watch
    Log in Domain List (Select your domain) Manage Advanced DNS
    Netlify Log in (Select your domain) Setup Netlify DNS
    Network Solutions Log in Account Manager My Domain Names (Select your domain) Manage Change Where Domain Points Advanced DNS
    Shopify
    Watch
    Log in Managed Domains (Select your domain) DNS Settings
    Squarespace Log in Home menu Settings Domains (Select your domain) Advanced settings Custom Records
    Vercel's Now Using "now" CLI now dns add [domain] '@' MX [record-value] [priority]
    Weebly Log in Domains page (Select your domain) DNS
    Wix Log in Domains page (Click icon) Select Manage DNS Records
    eNom Log in Domains My Domains
    Other
    Important: Don't see your registrar name listed here? Simply search on the Internet for "how to change DNS records on $REGISTRAR" (replacing $REGISTRAR with the name of your registrar – e.g. "how to change DNS records on GoDaddy" if you're using GoDaddy).
  3. Using your registrar's DNS management page (the other tab you have opened), set the following "MX" records:
    Important: Note that there should be NO other MX records set. Both records shown below MUST exist. Be sure there are no typos; and you have both mx1 and mx2 spelled correctly. If there were already MX records that existed, please delete them completely. The "TTL" value does not need to be 3600, it could be a lower or higher value if necessary.
    Name/Host/Alias TTL Type Priority Answer/Value
    "@", ".", or blank 3600 MX 10 mx1.forwardemail.net
    "@", ".", or blank 3600 MX 10 mx2.forwardemail.net
  4. Using your registrar's DNS management page (the other tab you have opened), set the following TXT record(s):
    Important: If you are on a paid plan, then you must completely skip this step and go to step five! If you are not on a paid plan, then your forwarded addresses will be publicly searchable – go to My Account Domains and upgrade your domain to a paid plan if desired. If you would like to learn more about paid plans see our Pricing page. Otherwise you can continue to choose one or more combinations from Option A to Option F listed below.

    Option A: If you are forwarding all emails from your domain, (e.g. "all@example.com", "hello@example.com", etc) to a specific address "user@gmail.com":
    Name/Host/Alias TTL Type Answer/Value
    "@", ".", or blank 3600 TXT forward-email=user@gmail.com
    Tip: Make sure to replace the values above in the "Value" column with your own email address. The "TTL" value does not need to be 3600, it could be a lower or higher value if necessary. A lower time to live ("TTL") value will ensure any future changes made to your DNS records are propagated throughout the Internet quicker – think of this as how long it will be cached in-memory (in seconds). You can learn more about TTL on Wikipedia.

    Option B: If you just need to forward a single email address (e.g. hello@example.com to user@gmail.com; this will also forward "hello+test@example.com" to "user+test@gmail.com" automatically):
    Name/Host/Alias TTL Type Answer/Value
    "@", ".", or blank 3600 TXT forward-email=hello:user@gmail.com

    Option C: If you are forwarding multiple emails, then you'll want to separate them with a comma:
    Name/Host/Alias TTL Type Answer/Value
    "@", ".", or blank 3600 TXT forward-email=hello:user@gmail.com,support:user@gmail.com

    Option D: You can have an infinite amount of forwarding emails setup – just make sure to not wrap over 255 characters in a single-line and start each line with "forward-email=". An example is provided below:
    Name/Host/Alias TTL Type Answer/Value
    "@", ".", or blank 3600 TXT forward-email=hello:user@gmail.com,support:user@gmail.com
    "@", ".", or blank 3600 TXT forward-email=help:user@gmail.com,foo:user@gmail.com
    "@", ".", or blank 3600 TXT forward-email=orders:user@gmail.com,baz:user@gmail.com
    "@", ".", or blank 3600 TXT forward-email=info:user@gmail.com,beep:user@gmail.com
    "@", ".", or blank 3600 TXT forward-email=errors:user@gmail.com,boop:user@gmail.com

    Option E: You can also specify a domain name in your TXT record to have global alias forwarding (e.g. "user@example.com" will get forwarded to "user@example.net"):
    Name/Host/Alias TTL Type Answer/Value
    "@", ".", or blank 3600 TXT forward-email=example.net

    Option F: You can even use webhooks as a global or individual alias to forward emails to. See the example and full section on webhooks titled Do you support webhooks below.
    Name/Host/Alias TTL Type Answer/Value
    "@", ".", or blank 3600 TXT forward-email=alias:https://requestbin.com/r/en8pfhdgcculn

    Option G: You can even use regular expressions ("regex") for matching aliases and for handling substitutions to forward emails to. See the examples and full section on regex titled Do you support regular expressions or regex below.
    Need advanced regex with substitution? See the examples and full section on regex titled Do you support regular expressions or regex below.
    Simple Example: If I want all emails that go to `linus@example.com` or `torvalds@example.com` to forward to `user@gmail.com`:
    Name/Host/Alias TTL Type Answer/Value
    "@", ".", or blank 3600 TXT forward-email=/^(linus|torvalds)$/:user@gmail.com

  5. Using your registrar's DNS management page (the other tab you have opened), additionally set the following TXT record:
    Name/Host/Alias TTL Type Answer/Value
    "@", ".", or blank 3600 TXT v=spf1 a mx include:spf.forwardemail.net -all
    Important: If you are using Gmail (e.g. Send Mail As) or G Suite, then you'll need to append include:_spf.google.com to the value above, for example:

    v=spf1 a mx include:spf.forwardemail.net include:_spf.google.com -all
    Tip: If you already have a similar line with "v=spf1", then you'll need to append include:spf.forwardemail.net right before any existing "include:host.com" records and before the "-all" in the same line, for example:

    v=spf1 a mx include:spf.forwardemail.net include:host.com -all

    Note that there is a difference between "-all" and "~all". The "-" indicates that the SPF check should FAIL if it does not match, and "~" indicates that the SPF check should SOFTFAIL. We recommend to use the "-all" approach to prevent domain forgery.

    You may also need to include the SPF record for whichever host you are sending mail from (e.g. Outlook).
  6. Verify your DNS records using our "Verify Records" tool available at My Account Domains Setup.
  7. Send a test email to confirm it works. Note that it might take some time for your DNS records to propagate.
    Tip: If you are not receiving test emails, or receive a test email that says "Be careful with this message", then see the answers for Why am I not receiving my test emails and Why are my test emails sent to myself in Gmail showing as "suspicious" respectively.
  8. If you wish to "Send Mail As" from Gmail, then you will need to watch this video, or follow the steps under How to Send Mail As Using Gmail below.
Congratulations! You've successfully completed all steps.
Tip: Optional add-ons are listed below. Note that these add-ons are completely optional and may not be necessary. We wanted to at least provide you with additional information if necessary.
Optional Add-on: If you're using the How to Send Mail As using Gmail feature, then you may want to add yourself to an allowlist. See these instructions by Gmail on this topic.

Yes, as of May 2023 we support sending email with SMTP as an add-on for all paid users.

Important: You are only permitted to use our outbound SMTP service for transactional emails. You are prohibited from sending marketing email (e.g. promotional, bulk, or commercial email to a list of contacts with the same content). This includes examples such as a newsletter or a bulk announcement email. Please ensure you have read our Terms, Privacy Policy, and Outbound SMTP Limits – your use is considered acknowledgement and agreement.
Important: If you are using Gmail, then refer to our Send Mail As with Gmail guide. If you are a developer, then refer to our email API docs – note that we do not support IMAP yet.
  1. Go to My Account Domains Settings Outbound SMTP Configuration and follow setup instructions

  2. Create a new alias for your domain under My Account Domains Aliases (e.g. hello@example.com)

  3. Click on Generate password next to the newly created alias. Copy to your clipboard and securely store the generated password shown on the screen.

  4. Using your preferred email application, add or configure an account with your newly created alias (e.g. hello@example.com)

    Tip: We recommend using Thunderbird, K-9 Mail, Apple Mail, or an open-source and privacy-focused alternative.
  5. When prompted for SMTP server name, enter smtp.forwardemail.net

  6. When prompted for SMTP server port, enter 587 (TLS) – see alternate SMTP ports if necessary

  7. When prompted for SMTP server password, paste the password from Generate password in step 3 above

  8. Save your settings and send your first test email – if you are having issues, then please contact us

Congratulations! You've successfully completed all steps.

We rate limit users and domains to 300 outbound SMTP messages per 1 day. This averages 9000+ emails in a calendar month. If you need to exceed this amount or have consistently large emails, then please contact us.

Our server is smtp.forwardemail.net and is also monitored on our status page.

It supports both IPv4 and IPv6 and is available over ports 587, 2587, 2525, and 25 for TLS (STARTTLS) – and 465 and 2465 for SSL.

Protocol Hostname Ports IPv4 IPv6
TLS (STARTTLS) smtp.forwardemail.net 587, 2587, 2525, 25
SSL smtp.forwardemail.net 465, 2465
Login Example Description
Username user@example.com Email address of an alias that exists for the domain at My Account Domains.
Password ************************ Alias-specific or domain-wide (coming soon) generated password.

In order to send outbound email with SMTP, the SMTP user must be the email address of an alias that exists for the domain at My Account Domains – and the SMTP password must be either an alias-specific or a domain-wide (coming soon) generated password.

Please refer to Do you support sending email with SMTP for step by step instructions.

Yes, as of May 2023 we support sending email with API as an add-on for all paid users.

Important: You are only permitted to use our outbound SMTP service for transactional emails. You are prohibited from sending marketing email (e.g. promotional, bulk, or commercial email to a list of contacts with the same content). This includes examples such as a newsletter or a bulk announcement email.

Please view our section on Emails in our API documentation for options, examples, and more insight.

In order to send outbound email with our API, you must use your API token available under My Security.

We plan to offer this feature in the near future.

Estimated Setup Time: Less than 10 minutes
Getting Started: If you've followed the instructions above under How do I get started and set up email forwarding, then you can continue reading below.
Important: You are only permitted to use our outbound SMTP service for transactional emails. You are prohibited from sending marketing email (e.g. promotional, bulk, or commercial email to a list of contacts with the same content). This includes examples such as a newsletter or a bulk announcement email. Please ensure you have read our Terms, Privacy Policy, and Outbound SMTP Limits – your use is considered acknowledgement and agreement.
Important: If you are a developer, then refer to our email API docs – note that we do not support IMAP yet.
  1. Go to My Account Domains Settings Outbound SMTP Configuration and follow setup instructions

  2. Create a new alias for your domain under My Account Domains Aliases (e.g. hello@example.com)

  3. Click on Generate password next to the newly created alias. Copy to your clipboard and securely store the generated password shown on the screen.

  4. Go to Gmail and under Settings Accounts and Import Send mail as, click "Add another email address"

  5. When prompted for "Name", enter the name that you want your email to be seen as "From" (e.g. "Linus Torvalds").

  6. When prompted for "Email address", enter the full email address of an alias you created under My Account Domains Aliases (e.g. hello@example.com)

  7. Uncheck "Treat as an alias"

  8. Click "Next Step" to proceed

  9. When prompted for "SMTP Server", enter smtp.forwardemail.net and leave the port as 587

  10. When prompted for "Username", enter the full email address of an alias you created under My Account Domains Aliases (e.g. hello@example.com)

  11. When prompted for "Password", paste the password from Generate password in step 3 above

  12. Leave the radio button checked for "Secured connection using TLS"

  13. Click "Add Account" to proceed

  14. Open a new tab to Gmail and wait for your verification email to arrive (you will receive a verification code that confirms you are the owner of the email address you are attempting to "Send Mail As")

  15. Once it arrives, copy and paste the verification code at the prompt you received in the previous step

  16. Once you've done that, go back to the email and click the link to "confirm the request". You will most likely need to do this step and the previous step for the email to be correctly configured.

Congratulations! You've successfully completed all steps.

Important: This legacy free guide is deprecated as of May 2023 since we now support outbound SMTP. If you use the guide below, then this will cause your outbound email to say "via forwardemail dot net" in Gmail.
Estimated Setup Time: Less than 10 minutes
Getting Started: If you've followed the instructions above under How do I get started and set up email forwarding, then you can continue reading below.
  1. You need to have Gmail's Two-Factor Authentication enabled for this to work. Visit https://www.google.com/landing/2step/ if you do not have it enabled.

  2. Once Two-Factor Authentication is enabled (or if you already had it enabled), then visit https://myaccount.google.com/apppasswords.

  3. When prompted for "Select the app and device you want to generate the app password for":

    • Select "Mail" under the drop-down for "Select app"
    • Select "Other" under the drop-down for "Select device"
    • When prompted for text input, enter your custom domain's email address you're forwarding from (e.g. hello@example.com - this will help you keep track in case you use this service for multiple accounts)
  4. Copy the password to your clipboard that is automatically generated

    Important: If you are using G Suite, visit your admin panel Apps G Suite Settings for Gmail Settings and make sure to check "Allow users to send mail through an external SMTP server...". There will be some delay for this change to be activated, so please wait a few minutes.
  5. Go to Gmail and under Settings Accounts and Import Send mail as, click "Add another email address"

  6. When prompted for "Name", enter the name that you want your email to be seen as "From" (e.g. "Linus Torvalds")

  7. When prompted for "Email address", enter the email address with the custom domain you used above (e.g. hello@example.com)

  8. Uncheck "Treat as an alias"

  9. Click "Next Step" to proceed

  10. When prompted for "SMTP Server", enter smtp.gmail.com and leave the port as 587

  11. When prompted for "Username", enter the portion of your Gmail address without the gmail.com part (e.g. just "user" if my email is user@gmail.com)

    Important: If the "Username" portion is autofilled, then you will need to change this to the username portion of your Gmail address instead.
  12. When prompted for "Password", paste from your clipboard the password you generated in step 2 above

  13. Leave the radio button checked for "Secured connection using TLS"

  14. Click "Add Account" to proceed

  15. Open a new tab to Gmail and wait for your verification email to arrive (you will receive a verification code that confirms you are the owner of the email address you are attempting to "Send Mail As")

  16. Once it arrives, copy and paste the verification code at the prompt you received in the previous step

  17. Once you've done that, go back to the email and click the link to "confirm the request". You will most likely need to do this step and the previous step for the email to be correctly configured.

If you're sending a test email to yourself, then it may not show up in your inbox because it has the same "Message-Id" header.

This is a widely known issue, and also affects services such as Gmail. Here is the official Gmail answer regarding this issue.

If you continue to have issues, then it is most likely to be an issue with DNS propagation. You will need to wait a bit longer and try again (or try setting a lower TTL value on your TXT records).

Still having issues? Please contact us so we can help investigate the issue and find a quick resolution.

Email relies on the SMTP protocol. This protocol consists of commands sent to a server (running most commonly on port 25). There is an initial connection, then the sender indicates who the mail is from ("MAIL FROM"), followed by where it's going to ("RCPT TO"), and finally the headers and the body of the email itself ("DATA"). The flow of our email forwarding system is described relative to each SMTP protocol command below:

  • Initial Connection (no command name, e.g. telnet example.com 25) - This is the initial connection. We check senders that aren't in our allowlist against our denylist. Finally, if a sender is not in our allowlist, then we check to see if they have been greylisted.

  • HELO - This indicates a greeting to identify the sender's FQDN, IP address, or mail handler name. This value can be spoofed, so we do not rely on this data and instead use the reverse hostname lookup of the connection's IP address.

  • MAIL FROM - This indicates the envelope mail from address of the email. If a value is entered, it must be a valid RFC 5322 email address. Empty values are permitted. We check for backscatter here, and we also check the MAIL FROM against our denylist. We finally check senders that are not on the allowlist for rate limiting (see the section on Rate Limiting and allowlist for more information).

  • RCPT TO - This indicates the recipient(s) of the email. These must be valid RFC 5322 email addresses. We only permit up to 50 envelope recipients per message (this is different than the "To" header from an email). We also check for a valid Sender Rewriting Scheme ("SRS") address here to protect against spoofing with our SRS domain name. Recipients provided that contain a "no-reply" address will receive a 553 error. See the complete list of "no-reply" addresses below. We also check the recipient against our denylist.

  • DATA - This is the core part of our service which processes an email. See the section How do you process an email for forwarding below for more insight.

This section describes our process related to the SMTP protocol command DATA in the section How does your email forwarding system work above – it is how we process an email's headers, body, security, determine where it needs to be delivered to, and how we handle connections.

  1. If the message exceeds the maximum size of 50mb, then it is rejected with a 552 error code.

  2. If the message did not have any headers, or headers were unable to be parsed, then it is rejected with a 421 error code.

  3. If the message did not contain a "From" header, or if any of the values in the "From" header were not valid RFC 5322 email addresses, then it is rejected with a 550 error code.

  4. If the message had more than 25 "Received" headers, then it was determined to have been stuck in a redirect loop, and it is rejected with a 550 error code.

  5. Using the email's fingerprint (see the section on Fingerprinting), we will check to see the message has been attempted to be retried for more than 5 days (which matches default postfix behavior), and if so, then it will be rejected with a 550 error code.

  6. If the message had a "To" header, and if any of the message's "To" headers were directed towards SRS rewritten addresses using our domain name, then we will rewrite them (this namely applies for vacation responders).

  7. We store in-memory the results from scanning the email using Spam Scanner.

  8. If there were any arbitrary results from Spam Scanner, then it is rejected with a 554 error code. Arbitrary results only include the GTUBE test at the time of this writing. See https://spamassassin.apache.org/gtube/ for more insight.

  9. We will add the following headers to the message for debugging and abuse prevention purposes:

    • X-Original-To - the original RCPT TO email address for the message.
      • This is useful for determining where an email was originally delivered to.
      • Will be released in v10+ of Forward Email.
      • Existing value if any is preserved as X-Original-Preserved-To.
    • X-ForwardEmail-Version - the current SemVer version from package.json of our codebase.
    • X-ForwardEmail-Session-ID - a session ID value used for debug purposes (only applies in non-production environments).
    • X-ForwardEmail-Sender - a comma separated list containing the original envelope MAIL FROM address (if it was not blank), the reverse PTR client FQDN (if it exists), and the sender's IP address.
    • X-Report-Abuse - with a value of abuse@forwardemail.net.
    • X-Report-Abuse-To - with a value of abuse@forwardemail.net.
    • X-Complaints-To - with a value of abuse@forwardemail.net.
  10. We then check the message for DKIM, SPF, ARC, and DMARC.

    • If the message failed DMARC and the domain had a rejection policy (e.g. p=reject was in the DMARC policy), then it is rejected with a 550 error code. Typically a DMARC policy for a domain can be found in the _dmarc sub-domain TXT record, (e.g. dig _dmarc.example.com txt).
    • If the message failed SPF and the domain had a hard fail policy (e.g. -all was in the SPF policy as opposed to ~all or no policy at all), then it is rejected with a 550 error code. Typically an SPF policy for a domain can be found in the TXT record for the root domain (e.g. dig example.com txt). See this section for more information on sending mail as with Gmail regarding SPF.
  11. Now we process the recipients of the message as collected from the RCPT TO command in the section How does your email forwarding system work above. For each recipient, we perform the following operations:

    • We lookup the TXT records of the domain name (the part after the @ symbol, e.g. example.com if the email address was test@example.com). For example, if the domain is example.com we do a DNS lookup such as dig example.com txt.
    • We parse all TXT records that start with either forward-email= (free plans) or forward-email-site-verification= (paid plans). Note that we parse both, in order to process emails while a user is upgrading or downgrading plans.
    • From these parsed TXT records, we iterate over them to extract the forwarding configuration (as described in the section How do I get started and set up email forwarding above). Note that we only support one forward-email-site-verification= value, and if more than one is supplied, then a 550 error will occur and the sender will receive a bounce for this recipient.
    • Recursively we iterate over the extracted forwarding configuration to determine global forwarding, regex based forwarding, and all other supported forwarding configurations – which are now known as our "Forwarding Addresses".
    • For each Forwarding Address, we support one recursive lookup (which will start this series of operations over on the given address). If a recursive match was found, then the parent result will be removed from Forwarding Addresses, and the children added.
    • Forwarding Addresses are parsed for uniqueness (since we don't want to send duplicates to one address or spawn additionally unnecessary SMTP client connections).
    • For each Forwarding Address, we lookup its domain name against our API endpoint /v1/max-forwarded-addresses (in order to determine how many addresses the domain is permitted to forward email to per alias, e.g. 10 by default – see the section on maximum limit on forwarding per alias). If this limit is exceeded, then a 550 error will occur and the sender will receive a bounce for this recipient.
    • We lookup the settings of the original recipient against our API endpoint /v1/settings, which supports a lookup for paid users (with a fallback for free users). This returns a configuration object for advanced settings for port (Number, e.g. 25), has_adult_content_protection (Boolean), has_phishing_protection (Boolean), has_executable_protection (Boolean), and has_virus_protection (Boolean).
    • Based off these settings, we then check against Spam Scanner results and if any errors occur, then the message is rejected with a 554 error code (e.g. if has_virus_protection is enabled, then we will check the Spam Scanner results for viruses). Note that all free plan users will be opted-in for checks against adult-content, phishing, executables, and viruses. By default, all paid plan users are opted-in as well, but this configuration can be altered under the Settings page for a domain in the Forward Email dashboard).
  12. For each processed recipient's Forwarding Addresses, we then perform the following operations:

    • The address is checked against our denylist, and if it was listed, then a 554 error code will occur and the sender will receive a bounce for this recipient.
    • If the address is a webhook, then we set a Boolean for future operations (see below – we group together similar webhooks to make one POST request vs. multiple for delivery).
    • If the address is an email address, then we parse the host for future operations (see below – we group together similar hosts to make one connection vs. multiple individual connections for delivery).
  13. If there are no recipients and there are no bounces, then we respond with a 550 error of "Invalid recipients".

  14. If there are recipients, then we iterate over them (grouped together by the same host) and deliver the emails. See the section How do you handle email delivery issues below for more insight.

    • If any errors occur while sending emails, then we will store them in-memory for later processing.
    • We will take the lowest error code (if any) from sending emails – and use that as the response code to the DATA command. This means that emails not delivered will typically be retried by the original sender, yet emails that were already delivered will not be re-sent the next time the message is sent (as we use Fingerprinting).
    • If no errors occurred, then we will send a 250 successful SMTP response status code.
    • A bounce is determined to be any delivery attempted that results in a status code that is >= 500 (permanent failures).
  15. If no bounces occurred (permanent failures), then we will return a SMTP response status code of the lowest error code from non-permanent failures (or a 250 successful status code if there were none).

  16. If bounces did occur then we will send bounce emails in the background after returning the lowest of all error codes to the sender. However, if the lowest error code is >= 500, then we do not send any bounce emails. This is because if we did, then senders would receive a double bounce email (e.g. one from their outbound MTA, such as Gmail – and also one from us). See the section on How do you protect against backscatter below for more insight.

Note that we will do a "Friendly-From" rewrite on the emails if and only if the DMARC policy of the sender was p=reject, AND it has a passing SPF, AND no DKIM signatures were aligned with the "From" header. This means that we will alter the "From" header on the message, set "X-Original-From", and also set a "Reply-To" if it was not already set. We will also re-seal the ARC seal on the message after altering these headers.

We also use smart-parsing of error messages at every level of our stack – in our code, DNS requests, Node.js internals, HTTP requests (e.g. 408, 413, and 429 are mapped to the SMTP response code of 421 if the recipient is a webhook), and mail server responses (e.g. responses with "defer" or "slowdown" would be retried as 421 errors).

Our logic is dummy-proof and it will also retry for TLS/SSL errors, connection issues, and more. The goal with dummy-proofing is to maximize deliverability to all recipients for a forwarding configuration.

If the recipient is a webhook, then we will permit a 60 second timeout for the request to complete with up to 3 retries (so 4 requests total before a failure). Note that we correctly parse error codes 408, 413, and 429 and map them to a SMTP response code of 421.

Otherwise if the recipient is an email address, then we will attempt to send the email with opportunistic TLS (we attempt to use STARTTLS if it is available on the recipient mail server). If a SSL or TLS error occurs while attempting to send the email, then we will attempt to send the email without TLS (without using STARTTLS).

If any DNS or connection errors occur, then we will return to the DATA command a SMTP response code of 421, otherwise if there are >= 500 level errors, then bounces will be sent.

If we detect that an email server we are attempting to deliver to has one or more of our mail exchange IP addresses blocked (e.g. by whatever technology they use for deferring spammers), then we will send a SMTP response code of 421 for the sender to retry their message later (and we are alerted to the issue so we can hopefully resolve it before the next attempt).

We routinely monitor all major DNS denylists and if any of our mail exchange ("MX") IP addresses are listed in a major denylist, we will pull it out of the relevant DNS A record round robin if possible until it the issue is resolved.

At the time of this writing, we are listed in several DNS allowlists as well, and we take monitoring denylists seriously. If you see any issues before we have a chance to resolve them, please notify us in writing at support@forwardemail.net.

We do not forward emails to "no-reply" addresses, and any sender attempting to will receive a 553 error.

Email usernames equal to any of the following (case-insensitive) are considered to be no-reply addresses:

  • do-not-reply
  • do-not-respond
  • do.not.reply
  • donotreply
  • donotrespond
  • dont-reply
  • naoresponda
  • no-replies
  • no-reply
  • no-replys
  • no.replies
  • no.reply
  • no.replys
  • no_reply
  • nobody
  • noreplies
  • noreply
  • noreplys

This list is maintained as an open-source project on GitHub.

Yes, we have a list of domain name extensions that are allowlisted by default and a dynamic, cached, and rolling allowlist based off strict criteria.

What domain name extensions are allowlisted by default

The following domain name extensions are considered to be allowlisted by default (regardless if they are on the Umbrella Popularity List or not):

  • edu
  • gov
  • mil
  • dni.us
  • fed.us
  • isa.us
  • kids.us
  • nsn.us
  • ak.us
  • al.us
  • ar.us
  • as.us
  • az.us
  • ca.us
  • co.us
  • ct.us
  • dc.us
  • de.us
  • fl.us
  • ga.us
  • gu.us
  • hi.us
  • ia.us
  • id.us
  • il.us
  • in.us
  • ks.us
  • ky.us
  • la.us
  • ma.us
  • md.us
  • me.us
  • mi.us
  • mn.us
  • mo.us
  • ms.us
  • mt.us
  • nc.us
  • nd.us
  • ne.us
  • nh.us
  • nj.us
  • nm.us
  • nv.us
  • ny.us
  • oh.us
  • ok.us
  • or.us
  • pa.us
  • pr.us
  • ri.us
  • sc.us
  • sd.us
  • tn.us
  • tx.us
  • ut.us
  • va.us
  • vi.us
  • vt.us
  • wa.us
  • wi.us
  • wv.us
  • wy.us
  • mil.tt
  • edu.tt
  • edu.tr
  • edu.ua
  • edu.au
  • ac.at
  • edu.br
  • ac.nz
  • school.nz
  • cri.nz
  • health.nz
  • mil.nz
  • parliament.nz
  • ac.in
  • edu.in
  • mil.in
  • ac.jp
  • ed.jp
  • lg.jp
  • ac.za
  • edu.za
  • mil.za
  • school.za
  • mil.kr
  • ac.kr
  • hs.kr
  • ms.kr
  • es.kr
  • sc.kr
  • kg.kr
  • edu.es
  • ac.lk
  • sch.lk
  • edu.lk
  • ac.th
  • mi.th
  • admin.ch
  • canada.ca
  • gc.ca
  • go.id
  • go.jp
  • go.ke
  • go.kr
  • go.th
  • gob.ar
  • gob.cl
  • gob.es
  • gob.mx
  • gob.pe
  • gob.ve
  • gouv.fr
  • gouv.nc
  • gouv.qc.ca
  • gov.ad
  • gov.af
  • gov.ai
  • gov.al
  • gov.am
  • gov.ao
  • gov.au
  • gov.aw
  • gov.ax
  • gov.az
  • gov.bd
  • gov.be
  • gov.bg
  • gov.bm
  • gov.br
  • gov.by
  • gov.cl
  • gov.cn
  • gov.co
  • gov.cy
  • gov.cz
  • gov.dz
  • gov.eg
  • gov.fi
  • gov.fk
  • gov.gg
  • gov.gr
  • gov.hk
  • gov.hr
  • gov.hu
  • gov.ie
  • gov.il
  • gov.im
  • gov.in
  • gov.iq
  • gov.ir
  • gov.it
  • gov.je
  • gov.kp
  • gov.krd
  • gov.ky
  • gov.kz
  • gov.lb
  • gov.lk
  • gov.lt
  • gov.lv
  • gov.ma
  • gov.mm
  • gov.mo
  • gov.mt
  • gov.my
  • gov.ng
  • gov.np
  • gov.ph
  • gov.pk
  • gov.pl
  • gov.pt
  • gov.py
  • gov.ro
  • gov.ru
  • gov.scot
  • gov.se
  • gov.sg
  • gov.si
  • gov.sk
  • gov.tr
  • gov.tt
  • gov.tw
  • gov.ua
  • gov.uk
  • gov.vn
  • gov.wales
  • gov.za
  • government.pn
  • govt.nz
  • gub.uy
  • gv.at
  • ac.uk
  • bl.uk
  • judiciary.uk
  • mod.uk
  • nhs.uk
  • parliament.uk
  • police.uk
  • rct.uk
  • royal.uk
  • sch.uk
  • ukaea.uk

What is your allowlist criteria

We have a static list of domain name extensions allowlisted by default – and we also maintain a dynamic, cached, rolling allowlist based off the following strict criteria:

  • Sender root domain must be of a domain name extension that matches the list we offer on our free plan (with the addition of biz and info). We also include edu, gov, and mil partial matches, such as xyz.gov.au and xyz.edu.au.
  • Sender root domain must be within top 100,000 unique root domain parsed results from Umbrella Popularity List ("UPL").
  • Sender root domain must be within top 50,000 results from unique root domains appearing in at least 4 of past 7 days of UPL's (~50%+).
  • Sender root domain must not be categorized as adult-content or malware by Cloudflare.
  • Sender root domain must have either A or MX records set.
  • Sender root domain must have either A record(s), MX record(s), DMARC record with p=reject or p=quarantine, or an SPF record with -all or ~all qualifier.

If this criteria is satisfied, then the sender root domain will be cached for 7 days. Note that our automated job runs daily – therefore this is a rolling allowlist cache that updates daily.

Our automated job will download the previous 7 days of UPL's in-memory, unzip them, and then parse in-memory according to the strict criteria above.

Popular domains at the time of this writing such as Google, Yahoo, Microsoft, Amazon, Meta, Twitter, Netflix, Spotify, and more – are of course included.

If you are a sender not in our allowlist, then the first time your FQDN root domain or IP address sends an email, you will be rate limited and greylisted. Note that this is standard practice adopted as an email standard. Most email server clients will attempt to retry if they receive a rate limit or greylist error (e.g. a 421 or 4xx level error status code).

Note that specific senders such as a@gmail.com, b@xyz.edu, and c@gov.au can still be denylisted (e.g. if we automatically detect spam, phishing, or malware from those senders).

As of March 31, 2023 we enforced a new blanket spam rule to protect our users and service.

This new rule allows only the following domain name extensions to be used on our free plan:

  • ai
  • app
  • au
  • ca
  • ch
  • co
  • com
  • de
  • dev
  • dk
  • es
  • family
  • fi
  • fm
  • fr
  • ie
  • im
  • io
  • is
  • it
  • jp
  • li
  • me
  • net
  • nl
  • no
  • nz
  • org
  • sh
  • sm
  • st
  • tv
  • uk
  • us
  • vc
  • xyz

Yes, we have a very lax email greylisting policy used. Greylisting only applies for senders not on our allowlist and lasts in our cache for 30 days.

For any new sender, we store a key in our Redis database for 30 days with a value set to the initial arrival time of their first request. We then reject their email with a retry status code of 450 and only allow it to pass once 5 minutes has passed.

If they have successfully waited for 5 minutes from this initial arrival time, then their emails will be accepted and they will not receive this 450 status code.

The key consists of either the FQDN root domain or the sender's IP address. This means that any sub-domain that passes the greylist also will pass for the root domain, and vice-versa (this is what we mean by a "very lax" policy).

For example, if an email comes from test.example.com before we see an email come from example.com, then any email from test.example.com and/or example.com will have to wait 5 minutes from the initial arrival time of the connection. We do not make both test.example.com and example.com each wait their own 5 minute periods (our greylisting policy applies at the root domain level).

Note that greylisting does not apply to any sender on our allowlist (e.g. Meta, Amazon, Netflix, Google, Microsoft at the time of this writing).

Yes, we operate our own private denylist and update it automatically in real-time and manually based off spam and malicious activity detected. Denied senders will receive a 554 error message.

We also pull from the UCEPROTECT Level 1 denylist at http://wget-mirrors.uceprotect.net/rbldnsd-all/dnsbl-1.uceprotect.net.gz every hour and feed it into our Redis database with a 7 day expiry.

Allowlist requests (or denylist removal requests) can be sent to allowlist@forwardemail.net (please provide a complete description and reason for being added to the allowlist, links to websites, and your businesses' certificate of formation to be listed in our allowlist).

Yes, we have rate limiting which applies only to senders not on the allowlist.

We only permit up to 100 connections per hour, per sender resolved FQDN root domain (or) sender remote IP address (if no reverse PTR is available), and per envelope recipient to. We store the key for rate limiting as a cryptographic hash in our Redis database.

If you are sending email through our system, please ensure you have a reverse PTR set up for all your IP addresses (otherwise each unique FQDN root domain or IP address you send from will be rate limited).

Note that if you send through a popular system such as Amazon SES, then you will not be rate limited since (at the time of this writing) Amazon SES is listed in our allowlist.

If you are sending from a domain such as test.abc.123.example.com, then the rate limit will be imposed on example.com. Many spammers use hundreds of sub-domains to work around common spam filters that only rate limit unique hostnames as opposed to unique FQDN root domains.

Senders that exceed the rate limit will be rejected with a 421 error.

Misdirected bounces or bounce spam (known as "Backscatter") can cause negative reputation to sender IP addreses.

We take two steps to protect against backscatter, which is detailed in the following sections Prevent bounces from known MAIL FROM spammers and Prevent unnecessary bounces to protect against backscatter below.

Prevent bounces from known MAIL FROM spammers

We pull the list from Backscatter.org (powered by UCEPROTECT) at http://wget-mirrors.uceprotect.net/rbldnsd-all/ips.backscatterer.org.gz every hour and feed it into our Redis database (we also compare the difference in advance; in case any IP's were removed that need to be honored).

If the MAIL FROM is blank OR contains (case-insensitive) one of the following usernames (the portion before the @ in an email), then we check to see if the sender IP matches one on this list:

  • abuse@
  • ftp@
  • hostmaster@
  • mailer-daemon@
  • mailer_daemon@
  • mailerdaemon@
  • news@
  • no-reply@
  • no_reply@
  • nobody@
  • noreplies@
  • noreply@
  • postmaster@
  • root@
  • security@
  • usenet@
  • webmaster@
  • www@

If the sender's IP is listed (and not in our allowlist), then we send a 554 error with the message The IP ${session.remoteAddress} is blocked by https://www.backscatterer.org/index.php?target=test&ip=${session.remoteAddress}. We will be alerted if a sender is on both the Backscatterer list and in our allowlist so we can resolve the issue if necessary.

The techniques described in this section adhere to the "SAFE MODE" recommendation at https://www.backscatterer.org/?target=usage – where we only check the sender IP if certain conditions have already been met.

Prevent unnecessary bounces to protect against backscatter

Bounces are emails that indicate email forwarding completely failed to the recipient and the email will not be retried.

A common reason for getting listed on the Backscatterer list is misdirected bounces or bounce spam, so we must protect against this in a few ways:

  1. We only send bounces when >= 500 status code errors occur (when emails attempted to be forwarded have failed, e.g. Gmail responds with a 500 level error).

  2. We only send bounces once and once only (we use a calculated bounce fingerprint key and store it in cache to prevent sending duplicates). The bounce fingerprint is a key that is the message's fingerprint combined with a hash of the bounce address and its error code). See the section on Fingerprinting for more insight into how the message fingerprint is calculated. Successfully sent bounce fingerprints will expire after 7 days in our Redis cache.

  3. We only send bounces when the MAIL FROM is not blank and does not contain (case-insensitive) one of the following usernames (the portion before the @ in an email). Note that this list is a little bit shorter than the one above in the MAIL FROM check because we don't want to have false positives (e.g. security@ is a valid address that you might want to get a bounce for; a lot of folks use security@ for their bug bounty programs).

    • abuse@
    • mailer-daemon@
    • mailer_daemon@
    • mailerdaemon@
  4. We don't send bounces if the original message had any of the following headers (case-insensitive):

    • Auto-Submitted (with a value of no)
    • X-Auto-Response-Suppress (with a value of dr, autoreply, auto-reply, auto_reply, or all)
    • List-Id
    • List-Unsubscribe
    • Feedback-ID
    • X-Auto-Reply
    • X-Autoreply
    • X-Auto-Respond
    • X-Autorespond
    • Precedence (with a value of bulk, autoreply, auto-reply, auto_reply, or list)

An email's fingerprint is used for determining uniqueness of an email and to prevent duplicate messages from being delivered and duplicate bounces from being sent.

The fingerprint is a series of cryptographically calculated hashes delimited by a colon, and it is used internally in our codebase.

These calculated hashes are pushed to an Array (a list) if and only if their values exist:

  • Client resolved FQDN hostname or IP address
  • Message-ID header value
  • Date header value (if and only if Message-ID did not exist)
  • From header value (if and only if Message-ID did not exist)
  • To header value (if and only if Message-ID did not exist)
  • Cc header value (if and only if Message-ID did not exist)
  • Subject header value (if and only if Message-ID did not exist)
  • Body value (if and only if Message-ID did not exist)

If you see this error message in Gmail when you send a test to yourself, or when a person you're emailing with your alias sees an email from you for the first time, then please do not worry – as this is a built-in safety feature of Gmail.

You can simply click "Looks safe". For example, if you were to send a test message using the send mail as feature (to someone else), then they will not see this message.

However if they do see this message, it's because they were normally used to seeing your emails come from john@gmail.com instead of john@customdomain.com (just an example). Gmail will alert the users just to make sure things are safe just in case, there is no workaround.

This topic is related to a widely known issue in Gmail where extra info appears next to a sender's name.

As of May 2023 we support sending email with SMTP as an add-on for all paid users – which means that you can remove the via forwardemail dot net in Gmail.

Note that this FAQ topic is specific for those using the How to Send Mail As using Gmail feature.

Please see the section on Do you support sending email with SMTP for configuration instructions.

Yes, as of May 5, 2020 we have added this feature. Right now the feature is domain-specific, as opposed to alias-specific. If you require it to be alias-specific, please contact us to let us know of your needs.

Enhanced Privacy Protection: If you are on a paid plan (which features enhanced privacy protection), then please go to My Account Domains, click on "Setup" next to your domain, and then click on "Settings". If you would like to learn more about paid plans see our Pricing page. Otherwise you can continue to follow the instructions below.

If you are on the free plan, then simply add a new DNS TXT record as shown below, but change the port from 25 to the port of your choosing.

For example, if I want all emails that go to example.com to forward to alias recipients' SMTP port of 1337 instead of 25:

Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email-port=1337
Tip: The most common scenario for custom port forwarding setup is when you want to forward all emails that go to example.com to a different port at example.com, other than the SMTP standard of port 25. To set this up, simply add the following TXT catch-all record.
Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=example.com

Yes! Automatic refunds occur when you upgrade, downgrade, or cancel your account within 30-days from when your plan first started. This only applies for first-time customers.

We do not pro-rate nor refund the difference when you switch plans. Instead we convert the remaining duration from your existing plan's expiration date into the closest relative duration for your new plan (rounded down by month).

Note that if you upgrade or downgrade between paid plans within a 30-day window since first starting a paid plan, then we will automatically refund the full amount from your existing plan.

Yes, as of May 15, 2020 we have added this feature. You can simply add webhook(s) exactly like you would with any recipient! Please ensure that you have the "http" or "https" protocol prefixed in the webhook's URL.

Enhanced Privacy Protection: If you are on a paid plan (which features enhanced privacy protection), then please go to My Account Domains and click on "Aliases" next to your domain to configure your webhooks. If you would like to learn more about paid plans see our Pricing page. Otherwise you can continue to follow the instructions below.

If you are on the free plan, then simply add a new DNS TXT record as shown below:

For example, if I want all emails that go to alias@example.com to forward to a new request bin test endpoint:

Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=alias:https://requestbin.com/r/en8pfhdgcculn

Or perhaps you want all emails that go to example.com to forward to this endpoint:

Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=https://requestbin.com/r/en8pfhdgcculn

Here are additional notes regarding webhooks:

  • If a webhook does not respond with a 200 status code, then we will store its response in the error log created – which is useful for debugging.

  • Webhook HTTP requests will retry up to 3 times every SMTP connection attempt, with a 60 second max timeout per endpoint POST request. Note that this does not mean that it only retries 3 times, it will actually retry continously over time by sending a SMTP code of 421 (which indicates to the sender retry later) after the 3rd failed HTTP POST request attempt. This means the email will retry continuously for days until a 200 status code is achieved.

  • We will retry automatically based off the default status and error codes used in superagent's retry method (we are maintainers).

  • We group together webhook HTTP requests to the same endpoint in one request instead of multiple) in order to save resources and speed up response time. For example, if you send an email to webhook1@example.com, webhook2@example.com, and webhook3@example.com, and all of these are configured to hit the same exact endpoint URL, then only one request will be made. We group together by exact endpoint matching with strict equality.

  • Note that we use the mailparser library's "simpleParser" method to parse the message into a JSON friendly object.

  • Raw email value as a String is given as the property "raw".

  • Authentication results are given as properties "dkim", "spf", "arc", "dmarc", and "bimi".

  • The parsed email headers is given as the property "headers" – but also note you can use "headerLines" for easier iteration and parsing.

  • The grouped recipients for this webhook are grouped together and given as the property "recipients".

  • The SMTP session information is given as the property "session". This contains information about the sender of the message, arrival time of the message, HELO, and client hostname. The client hostname value as session.clientHostname is either the FQDN (from a reverse PTR lookup) or it is session.remoteAddress wrapped in brackets (e.g. "[127.0.0.1]").

  • If you need a quick way to get the value of X-Original-To, then you can use the value of session.recipient (see example below). The header X-Original-To is a header we add to messages for debugging with the original RCPT TO email address for the message.

  • If there are attachments, they will be appended to the attachments Array with Buffer values. You can parse them back into content using an approach with JavaScript such as:

    const data = [
      104,
      101,
      108,
      108,
      111,
      32,
      119,
      111,
      114,
      108,
      100,
      33
    ];
    
    //
    // outputs "hello world!" to the console
    // (this is the content from the filename "text1.txt" in the example JSON request payload above)
    //
    console.log(Buffer.from(data).toString());
    
Tip: Curious what the webhook request looks like from forwarded emails? We've included an example below for you!
{
  "attachments": [
    {
      "type": "attachment",
      "content": {
        "type": "Buffer",
        "data": [
          104,
          101,
          108,
          108,
          111,
          32,
          119,
          111,
          114,
          108,
          100,
          33
        ]
      },
      "contentType": "text/plain",
      "partId": "2",
      "release": null,
      "contentDisposition": "attachment",
      "filename": "text1.txt",
      "headers": {},
      "checksum": "fc3ff98e8c6a0d3087d515c0473f8677",
      "size": 12
    }
  ],
  "headers": "ARC-Seal: i=1; a=rsa-sha256; t=1653506802; cv=none; d=forwardemail.net;\r\n s=default;\r\n b=R6QJ0tGwwjg2VPxiAlVIKxsg3jEPtRGKPTIOdZNWuhWrbssttFdOYzRRqvacDyN5SLoyDhVye\r\n DUA/64IxANXdHVFlpR258Yp7WxLDv2gtJD5vNSKYmUJZOWk1TynmlqTYrp0Vuqg2xIUjIlPBWAJ\r\n PPNx4JvOLjJuWYynU2qIWz0=\r\nARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed;\r\n d=forwardemail.net; h=MIME-Version: Date: Message-ID: From: Content-Type;\r\n q=dns/txt; s=default; t=1653506802;\r\n bh=cEYDoyTy+Ub29XZt/zXR+sprfUE6BW0y5cHfah01PT4=;\r\n b=F/t56AAXr2Kv3G6VsbdT5OKDVJf2ulhwLiTM18Ra4tDPUKPSGSLKrWvxiXEg5NMWwdWnsOYrL\r\n r3YSm4uMxVMhHZbHm/sUu4QZq5/18hQsAkCv6fI9ifTjDwBrN5zpLOhPoZFFo+TyvHxiII3Xv3L\r\n UEzmUIIaJRX6tboQ160tino=\r\nARC-Authentication-Results: i=1; mx1.forwardemail.net;\r\n dkim=none (message not signed);\r\n spf=none (mx1.forwardemail.net: example.net does not designate permitted sender hosts) smtp.mailfrom=test@example.net smtp.helo=user.oem.local;\r\n dmarc=none header.from=example.com;\r\n bimi=skipped (DMARC not enabled)\r\nReceived-SPF: none (mx1.forwardemail.net: example.net does not designate permitted sender hosts) client-ip=127.0.0.1;\r\nAuthentication-Results: mx1.forwardemail.net;\r\n dkim=none (message not signed);\r\n spf=none (mx1.forwardemail.net: example.net does not designate permitted sender hosts) smtp.mailfrom=test@example.net smtp.helo=user.oem.local;\r\n dmarc=none header.from=example.com;\r\n bimi=skipped (DMARC not enabled)\r\n",
  "headerLines": [
    {
      "key": "arc-seal",
      "line": "ARC-Seal: i=1; a=rsa-sha256; t=1653506802; cv=none; d=forwardemail.net;\r\n s=default;\r\n b=R6QJ0tGwwjg2VPxiAlVIKxsg3jEPtRGKPTIOdZNWuhWrbssttFdOYzRRqvacDyN5SLoyDhVye\r\n DUA/64IxANXdHVFlpR258Yp7WxLDv2gtJD5vNSKYmUJZOWk1TynmlqTYrp0Vuqg2xIUjIlPBWAJ\r\n PPNx4JvOLjJuWYynU2qIWz0="
    },
    {
      "key": "arc-message-signature",
      "line": "ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed;\r\n d=forwardemail.net; h=MIME-Version: Date: Message-ID: From: Content-Type;\r\n q=dns/txt; s=default; t=1653506802;\r\n bh=cEYDoyTy+Ub29XZt/zXR+sprfUE6BW0y5cHfah01PT4=;\r\n b=F/t56AAXr2Kv3G6VsbdT5OKDVJf2ulhwLiTM18Ra4tDPUKPSGSLKrWvxiXEg5NMWwdWnsOYrL\r\n r3YSm4uMxVMhHZbHm/sUu4QZq5/18hQsAkCv6fI9ifTjDwBrN5zpLOhPoZFFo+TyvHxiII3Xv3L\r\n UEzmUIIaJRX6tboQ160tino="
    },
    {
      "key": "arc-authentication-results",
      "line": "ARC-Authentication-Results: i=1; mx1.forwardemail.net;\r\n dkim=none (message not signed);\r\n spf=none (mx1.forwardemail.net: example.net does not designate permitted sender hosts) smtp.mailfrom=test@example.net smtp.helo=user.oem.local;\r\n dmarc=none header.from=example.com;\r\n bimi=skipped (DMARC not enabled)"
    },
    {
      "key": "received-spf",
      "line": "Received-SPF: none (mx1.forwardemail.net: example.net does not designate permitted sender hosts) client-ip=127.0.0.1;"
    },
    {
      "key": "authentication-results",
      "line": "Authentication-Results: mx1.forwardemail.net;\r\n dkim=none (message not signed);\r\n spf=none (mx1.forwardemail.net: example.net does not designate permitted sender hosts) smtp.mailfrom=test@example.net smtp.helo=user.oem.local;\r\n dmarc=none header.from=example.com;\r\n bimi=skipped (DMARC not enabled)"
    },
    {
      "key": "x-forwardemail-sender",
      "line": "X-ForwardEmail-Sender: rfc822; test@example.net"
    },
    {
      "key": "x-forwardemail-session-id",
      "line": "X-ForwardEmail-Session-ID: w2czxgznghn5ryyw"
    },
    {
      "key": "x-forwardemail-version",
      "line": "X-ForwardEmail-Version: 9.0.0"
    },
    {
      "key": "content-type",
      "line": "Content-Type: multipart/mixed; boundary=\"--_NmP-179a735428ca7575-Part_1\""
    },
    {
      "key": "from",
      "line": "From: some <random@example.com>"
    },
    {
      "key": "message-id",
      "line": "Message-ID: <69ad5fc2-91cb-728f-ae5c-eeedc5f267b6@example.net>"
    },
    {
      "key": "date",
      "line": "Date: Wed, 25 May 2022 19:26:41 +0000"
    },
    {
      "key": "mime-version",
      "line": "MIME-Version: 1.0"
    }
  ],
  "html": "<strong>some random text</strong>",
  "text": "some random text",
  "textAsHtml": "<p>some random text</p>",
  "date": "2022-05-25T19:26:41.000Z",
  "from": {
    "value": [
      {
        "address": "random@example.com",
        "name": "some"
      }
    ],
    "html": "<span class=\"mp_address_group\"><span class=\"mp_address_name\">some</span> &lt;<a href=\"mailto:random@example.com\" class=\"mp_address_email\">random@example.com</a>&gt;</span>",
    "text": "some <random@example.com>"
  },
  "messageId": "<69ad5fc2-91cb-728f-ae5c-eeedc5f267b6@example.net>",
  "raw": "ARC-Seal: i=1; a=rsa-sha256; t=1653506802; cv=none; d=forwardemail.net;\r\n s=default;\r\n b=R6QJ0tGwwjg2VPxiAlVIKxsg3jEPtRGKPTIOdZNWuhWrbssttFdOYzRRqvacDyN5SLoyDhVye\r\n DUA/64IxANXdHVFlpR258Yp7WxLDv2gtJD5vNSKYmUJZOWk1TynmlqTYrp0Vuqg2xIUjIlPBWAJ\r\n PPNx4JvOLjJuWYynU2qIWz0=\r\nARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed;\r\n d=forwardemail.net; h=MIME-Version: Date: Message-ID: From: Content-Type;\r\n q=dns/txt; s=default; t=1653506802;\r\n bh=cEYDoyTy+Ub29XZt/zXR+sprfUE6BW0y5cHfah01PT4=;\r\n b=F/t56AAXr2Kv3G6VsbdT5OKDVJf2ulhwLiTM18Ra4tDPUKPSGSLKrWvxiXEg5NMWwdWnsOYrL\r\n r3YSm4uMxVMhHZbHm/sUu4QZq5/18hQsAkCv6fI9ifTjDwBrN5zpLOhPoZFFo+TyvHxiII3Xv3L\r\n UEzmUIIaJRX6tboQ160tino=\r\nARC-Authentication-Results: i=1; mx1.forwardemail.net;\r\n dkim=none (message not signed);\r\n spf=none (mx1.forwardemail.net: example.net does not designate permitted sender hosts) smtp.mailfrom=test@example.net smtp.helo=user.oem.local;\r\n dmarc=none header.from=example.com;\r\n bimi=skipped (DMARC not enabled)\r\nReceived-SPF: none (mx1.forwardemail.net: example.net does not designate permitted sender hosts) client-ip=127.0.0.1;\r\nAuthentication-Results: mx1.forwardemail.net;\r\n dkim=none (message not signed);\r\n spf=none (mx1.forwardemail.net: example.net does not designate permitted sender hosts) smtp.mailfrom=test@example.net smtp.helo=user.oem.local;\r\n dmarc=none header.from=example.com;\r\n bimi=skipped (DMARC not enabled)\r\nX-ForwardEmail-Sender: rfc822; test@example.net\r\nX-ForwardEmail-Session-ID: w2czxgznghn5ryyw\r\nX-ForwardEmail-Version: 9.0.0\r\nContent-Type: multipart/mixed; boundary=\"--_NmP-179a735428ca7575-Part_1\"\r\nFrom: some <random@example.com>\r\nMessage-ID: <69ad5fc2-91cb-728f-ae5c-eeedc5f267b6@example.net>\r\nDate: Wed, 25 May 2022 19:26:41 +0000\r\nMIME-Version: 1.0\r\n\r\n----_NmP-179a735428ca7575-Part_1\r\nContent-Type: multipart/alternative;\r\n boundary=\"--_NmP-179a735428ca7575-Part_2\"\r\n\r\n----_NmP-179a735428ca7575-Part_2\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Transfer-Encoding: 7bit\r\n\r\nsome random text\r\n----_NmP-179a735428ca7575-Part_2\r\nContent-Type: text/html; charset=utf-8\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<strong>some random text</strong>\r\n----_NmP-179a735428ca7575-Part_2--\r\n\r\n----_NmP-179a735428ca7575-Part_1\r\nContent-Type: text/plain; name=text1.txt\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=text1.txt\r\n\r\naGVsbG8gd29ybGQh\r\n----_NmP-179a735428ca7575-Part_1--\r\n",
  "dkim": {
    "headerFrom": [
      "random@example.com"
    ],
    "envelopeFrom": "test@example.net",
    "results": [
      {
        "status": {
          "result": "none",
          "comment": "message not signed"
        },
        "info": "dkim=none (message not signed)"
      }
    ]
  },
  "spf": {
    "domain": "example.net",
    "client-ip": "127.0.0.1",
    "helo": "user.oem.local",
    "envelope-from": "test@example.net",
    "status": {
      "result": "none",
      "comment": "mx1.forwardemail.net: example.net does not designate permitted sender hosts",
      "smtp": {
        "mailfrom": "test@example.net",
        "helo": "user.oem.local"
      }
    },
    "header": "Received-SPF: none (mx1.forwardemail.net: example.net does not designate permitted sender hosts) client-ip=127.0.0.1;",
    "info": "spf=none (mx1.forwardemail.net: example.net does not designate permitted sender hosts) smtp.mailfrom=test@example.net smtp.helo=user.oem.local",
    "lookups": {
      "limit": 50,
      "count": 1
    }
  },
  "arc": {
    "status": {
      "result": "none"
    },
    "i": 0,
    "authResults": "mx1.forwardemail.net;\r\n dkim=none (message not signed);\r\n spf=none (mx1.forwardemail.net: example.net does not designate permitted sender hosts) smtp.mailfrom=test@example.net smtp.helo=user.oem.local;\r\n dmarc=none header.from=example.com;\r\n bimi=skipped (DMARC not enabled)"
  },
  "dmarc": {
    "status": {
      "result": "none",
      "header": {
        "from": "example.com"
      }
    },
    "domain": "example.com",
    "info": "dmarc=none header.from=example.com"
  },
  "bimi": {
    "status": {
      "header": {},
      "result": "skipped",
      "comment": "DMARC not enabled"
    },
    "info": "bimi=skipped (DMARC not enabled)"
  },
  "recipients": [
    "webhook1@webhooks.net"
  ],
  "session": {
    "recipient": "webhook1@webhooks.net",
    "remoteAddress": "127.0.0.1",
    "remotePort": 65138,
    "clientHostname": "[127.0.0.1]",
    "hostNameAppearsAs": "user.oem.local",
    "sender": "test@example.net",
    "mta": "mx1.forwardemail.net",
    "arrivalDate": "2022-05-25T19:26:41.423Z",
    "arrivalTime": 1653506801423
  }
}

Yes, as of September 27, 2021 we have added this feature. You can simply write regular expressions ("regex") for matching aliases and performing substitions.

Regular expression supported aliases are ones that start with a / and end with / and their recipients are email addresses or webhooks. The recipients can also include regex substitution support (e.g. $1, $2).

We support two regular expression flags including i and g. The case-insensitive flag of i is a permanent default and it is always enforced. The global flag of g can be added by you by affixing the ending / with /g.

Note that we also support our disabled alias feature for the recipient portion with our regex support.

Regular expressions are not supported on global vanity domains (as this could be a security vulnerability).

Enhanced Privacy Protection: If you are on a paid plan (which features enhanced privacy protection), then please go to My Account Domains and click on "Aliases" next to your domain to configure regular expressions. If you would like to learn more about paid plans see our Pricing page. Otherwise you can continue to follow the instructions below.

If you are on the free plan, then simply add a new DNS TXT record using one or more of the provided examples below:

Simple Example: If I want all emails that go to `linus@example.com` or `torvalds@example.com` to forward to `user@gmail.com`:
Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=/^(linus|torvalds)$/:user@gmail.com
Firstname Lastname Substitution Example: Imagine all of your company email addresses are of the `firstname.lastname@example.com` pattern. If I want all emails that go to the pattern of `firstname.lastname@example.com` to forward to `firstname.lastname@company.com` with substitution support (view test on RegExr):
Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=/^([A-Za-z]+)+\.([A-Za-z]+)+$/:$1.$2@company.com
Plus Symbol Filtering Substitution Example: If I want all emails that go to `info@example.com` or `support@example.com` to forward to `user+info@gmail.com` or `user+support@gmail.com` respectively (with substitution support) (view test on RegExr):
Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=/^(support|info)$/:user+$1@gmail.com
Webhook Querystring Substitution Example: Perhaps you want all emails that go to `example.com` to go to a webhook and have a dynamic querystring key of "to" with a value of the username portion of the email address (view test on RegExr):
Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=/^(.*?)$/:https://example.com/webhook?username=$1
Disable Example: If you want all emails that match a certain pattern to be disabled (see Can I disable specific aliases), then simply use the same approach with an exclamation mark "!":
Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=/^(linus|torvalds)$/:!
Tip: Curious how to write a regular expression or need to test your replacement? You can go to the free regular expression testing website RegExr at https://regexr.com.

No, it is not recommended, as you can only use one mail exchange server at a time. Fallbacks are usually never retried due to priority misconfigurations and mail servers not respecting MX exchange priority checking.

Important: If you are on a paid plan, then you must go to My Account Domains Aliases Edit Alias Uncheck "Active" checkbox Continue.

Yes! As of February 6, 2020 we have added this feature. Simply edit your DNS TXT record and prefix the alias with an exclamation mark. Note that you must preserve the ":" mapping, as this is required if you ever decide to toggle this off (and it's also used for importing in our paid plans).

If you prefix an alias with "!" (exclamation mark) then it will still return successful respond codes to senders attempting to send to this address, but the emails themselves will go nowhere; to a blackhole.

Emails sent to disabled addresses will respond with a SMTP response status code of 250 (accepted), but the emails will not actually be delivered to the recipient(s).

For example, if I want all emails that go to alias@example.com to stop flowing through to user@gmail.com:

Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=!alias:user@gmail.com
Tip: You can also rewrite the forwarded recipient's address to simply "nobody@forwardemail.net", which will route it to nobody as in the example below.
Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=!alias:nobody@forwardemail.net
Tip: If you want increased security, then you can also remove the ":user@gmail.com" (or ":nobody@forwardemail.net") part, leaving just "!alias" as in the example below.
Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=!alias

Yes, absolutely. Just specify multiple recipients in your TXT records.

For example, if I want an email that goes to hello@example.com to get forwarded to user+a@gmail.com and user+b@gmail.com, then my TXT record would look like this:

Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=hello:user+a@gmail.com,hello:user+b@gmail.com

Or, you could specify them in two separate lines, such as this:

Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=hello:user+a@gmail.com
"@", ".", or blank 3600 TXT forward-email=hello:user+b@gmail.com

It's up to you!

Yes, you can. Just specify multiple global catch-all recipients in your TXT records.

For example, if I want every email that goes to *@example.com (the asterisk meaning its a wildcard aka catch-all) to get forwarded to user+a@gmail.com and user+b@gmail.com, then my TXT record would look like this:

Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=user+a@gmail.com,user+b@gmail.com

Or, you could specify them in two separate lines, such as this:

Name/Host/Alias TTL Type Answer/Value
"@", ".", or blank 3600 TXT forward-email=user+a@gmail.com
@, ".", or blank 3600 TXT forward-email=user+b@gmail.com

It's up to you!

Yes, the default limit is 10. This does NOT mean that you can only have 10 aliases on your domain name. You can have as many aliases as you want (an unlimited amount). It means that you can only forward one alias to 10 unique email addresses. You could have hello:user+1@gmail.com, hello:user+2@gmail.com, hello:user+3@gmail.com, … (from 1-10) – and any emails to hello@example.com would get forwarded to user+1@gmail.com, user+2@gmail.com, user+3@gmail.com, … (from 1-10).

Tip: Need more than 10 recipients per alias? Send us an email and we would be happy to increase your accounts limit.

Yes, you can, however you still must adhere to the maximum limit. If you have hello:linus@example.com and linus:user@gmail.com, then emails to hello@example.com would get forwarded to linus@example.com and user@gmail.com. Note that an error will be thrown if you attempt to recursively forward emails.

We use MX and TXT record verification, therefore if you add this service's respective MX and TXT records, then you're registered. If you remove them, then you're unregistered. You have ownership of your domain and DNS management, so if someone has access to that then that's a problem.

The service continues to run thanks to users that upgraded to paid plans. We want to provide a free alternative for people that are using closed-source forwarding services (and subsequently risking their privacy and security).

We default to a 50MB size limit, which includes content, headers, and attachments. Note that services such as Gmail and Outlook allow only 25MB size limit, and if you exceed the limit when sending to addresses at those providers you will receive an error message.

An error with the proper response code is returned if the file size limit is exceeded.

No, we do not write to disk or store logs – with the exception of errors and outbound SMTP (see our Privacy Policy).

Everything is done in-memory and our source code is on GitHub.

No, we do not write to disk or store logs – with the exception of errors and outbound SMTP (see our Privacy Policy).

Everything is done in-memory and our source code is on GitHub.

Yes. You can access error logs under My Account → Logs or My Account → Domains.

As of February 2023, we store error logs for 4xx and 5xx SMTP response codes for a period of 7 days – which contain the SMTP error, envelope, and email headers (we do not store the email body nor attachments).

Error logs allow you to check for missing important emails and mitigate spam false positives for your domains. They are also a great resource for debugging issues with email webhooks (since the error logs contain the webhook endpoint response).

Error logs for rate limiting and greylisting are not accessible since the connection ends early (e.g. before RCPT TO and MAIL FROM commands can be transmitted).

See our Privacy Policy for more insight.

No, absolutely not. See our Privacy Policy.

Many other email forwarding services store and could potentially read your email. There is no reason why forwarded emails need to be stored to disk storage – and therefore we architected the first open-source solution that does it all in-memory.

We believe you should have a right to privacy and we strictly respect it. The code that is deployed to the server is open-source software on GitHub for transparency and to build trust.

Yes, absolutely.

Yes, absolutely. Instead of using "@", ".", or blank as the name/host/alias, you just use the sub-domain name as the value instead.

If you want foo.example.com to forward emails, then enter foo as the name/host/alias value in your DNS settings (for both MX and TXT records).

Yes, absolutely.

Yes, it has tests written with ava and also has code coverage.

Yes, absolutely. For example if you're sending an email to hello@example.com and it's registered to forward to user@gmail.com, then the SMTP response message and code from the "gmail.com" SMTP server will be returned instead of the proxy server at "mx1.forwardemail.net" or "mx2.forwardemail.net".

You should unsubscribe from the emailing list (if possible) and block the sender.

Please do not report the message as spam, but instead forward it to our manually curated and privacy-focused abuse prevention system.

The email address to forward spam to is: abuse@forwardemail.net

Yes! As of October 2, 2018 we have added this feature. See How to Send Mail As using Gmail above!

You should also set the SPF record for Gmail in your DNS configuration TXT record.

Important: If you are using Gmail (e.g. Send Mail As) or G Suite, then you'll need to append include:_spf.google.com to your SPF TXT record, for example:

v=spf1 a mx include:spf.forwardemail.net include:_spf.google.com -all

Yes! As of October 2, 2018 we have added this feature. Simply view these two links from Microsoft below:

You should also set the SPF record for Outlook in your DNS configuration TXT record.

Important: If you are using Microsoft Outlook or Live.com, you'll need to append include:spf.protection.outlook.com to your SPF TXT record, for example:

v=spf1 a mx include:spf.forwardemail.net include:spf.protection.outlook.com -all

Unfortunately Apple does not allow this, regardless of which service you use. However you can use the Mail app along with your domain's email account.

Yes, however "relatively unknown" senders are rate limited to 100 connections per hour per hostname or IP. See the section on Rate Limiting and Greylisting above.

By "relatively unknown", we mean senders that do not appear in the allowlist.

If this limit is exceeded we send a "421" response code which tells the senders mail server to retry again later.

If you're using Gmail, then follow these steps below:

  1. Go to https://google.com and sign out of all email accounts
  2. Click "Sign In" and on the drop-down click on "other account"
  3. Select "Use another account"
  4. Select "Create account"
  5. Select "Use my current email address instead"
  6. Enter your custom domain name email address
  7. Retrieve the verification email sent to your email address
  8. Enter the verification code from this email
  9. Complete profile information for your new Google account
  10. Agree to all Privacy and Terms of Use policies
  11. Go to https://google.com and in the top right corner, click on your profile icon, and click on the "change" button
  12. Upload a new photo or avatar for your account
  13. Changes will take approximately 1-2 hours to propagate, but sometimes may be very quick.
  14. Send a test email and the profile photo should appear.

The Free plan requires you to use public DNS records to store your forwarding configuration. Anyone with a computer can lookup your forwarding configuration in a terminal if you are on the Free plan. Unlike the Free plan, the Enhanced Protection plan uses a cryptographically generated random string to store your forwarding configuration privately.

Free Plan Enhanced Protection Plan
forward-email=user@gmail.com forward-email-site-verification=m8d7o8K4Il

Yes, as of March 2, 2023 we support MTA-STS. You can use this template if you wish to enable it on your domain.

Yes. We have built-in support for SPF, DKIM, DMARC, ARC, and SRS across all plans. We have also worked extensively with the original authors of these specifications and other email experts to ensure perfection and high deliverability.

Yes. Regardless of which plan you are on, you will pay only one monthly rate – which covers all of your domains.

We accept cards, wallets, and bank transfers using Stripe and PayPal – for one-time payments or monthly, quarterly, or yearly subscriptions.

No. Prices will never increase. Unlike other companies, we will never shutdown our service either.

We created an open-source software project called 🍊 Tangerine and use it for DNS lookups. The default DNS servers used are 1.1.1.1 and 1.0.0.1, and DNS queries are through DNS over HTTPS ("DoH") at the application layer.

🍊 Tangerine uses CloudFlare's privacy-first consumer DNS service by default.