GNU/Linux, Open Source, Cloud Computing, DevOps and more...

Use GMail with your own domain for free thanks to Amazon SES & Lambda


One of the main needs of a small business or startup is to have a reliable mail system with its own domain that helps differentiate on the Internet. Although there are lots of hosting plans offering free email accounts and even you could set up your own mail server, you are probably already used to mail services like GMail and would like to continue using it to also manage mail from your own domain without having to come to paid solutions such as G Suite (formerly Google Apps), which though inexpensive for the services you get in return, they represent an additional cost that your incipient project might not afford.

If this is your case you will be happy to know that thanks to the free tier offered by Amazon Web Services (AWS) in some of its services such as Amazon SES and Lambda, you can build a mail system at no cost that integrates seamlessly with your GMail free account, and at the same time allows you to send and receive mail from multiple mailboxes within your own domain.

The procedure below is not exclusive to GMail accounts. Any other email service that lets you send mail choosing the name and address you want to appear in the From: field will be suitable. Receiving mail from your domain does not even require any additional feature, so any email service, whether Office 365 Outlook, Yahoo or iCloud Mail will do.

IMPORTANT: Check out the limits of AWS free tier and the costs you will incur if you exceed them. Even though they are quite broad for the purpose of this article, they could result in an economic loss that was not planned. Remember that if you carry out this procedure you do it under your entire responsibility.

1. Create new DNS zone for your domain on Amazon Route 53

The first step is to create a Public Hosted Zone for your domain on Amazon Route 53 if you don’t have it yet. To do this, access to AWS console and go to Route 53 -> Hosted zones -> Create Hosted Zone. You can harness this step to add some DNS entries if you need them, such as A records that point to your website or SPF record as a security measure to prevent the email addresses within your domain from being spoofed or your messages from being considered as spam.

Basic public DNS zone newly created in Amazon Route 53

Basic public DNS zone newly created in Amazon Route 53

Example SPF record in DNS zone

Example SPF record in DNS zone

2. Verify your domain on Amazon SES

Open a new browser tab and go to Amazon SES service through the AWS console. Choose the Domains menu option and verify your domain, which will cause new DNS registers to be created in your Route 53 DNS zone as you can see in the following images:

Domain verification in Amazon SES

Domain verification in Amazon SES

Domain verification result

Domain verification result

New DNS records added to zone

New DNS records added to zone

IMPORTANT: Route 53 DNS zones cost $0.50/month per domain. If you don’t want to incur this expense, you can copy at this point all DNS records that appear in the last screenshot to the DNS management console of your current domain registrar or other DNS provider. If you prefer to use the Route 53 service you will have to update your current domain’s DNS servers and put in place those provided by Amazon (NS records of the last screenshot).

3. Create a Lambda function to forward incoming mail to your GMail account

This point includes two steps. In the first place you will create a Lambda function by opening the main page of Amazon Lambda service in a new browser tab and clicking on Create a Lambda function. You will select a Blank Function and skip Configure triggers step. In the screenshots below you can see the form fields that need to be filled in order to create the needed Lambda function.

The Node.js source code for this Lambda function is based on this GitHub repo: The following are the only changes I had to make in that code to illustrate my example, which has been tested and works satisfactorily:

var defaultConfig = {
 fromEmail: "",
 subjectPrefix: "",
 emailBucket: "example-com-mailbox",
 //emailKeyPrefix: "emailsPrefix/",
 emailKeyPrefix: "",
 forwardMapping: {
 "": [

The second step revolves around modifying the security policies associated with the IAM role that is automatically generated when creating our Lambda function. You need to add two new policies: one to allow access to the S3 bucket that will be created later to store mail messages, and another one to access the resources on Amazon SES service. To do this, once the Lambda function is created, open IAM service in a new browser tab and click on the following options: Roles -> example-com-forwarding -> Policy Name AWSLambdaBasicExecutionRole-99b88501-cad9-4f48-ba03-75b13f98dae0 -> Edit Policy. In that last page add the JSON code in blue in the following screenshots:

Lambda configuration for email forwarding

Lambda configuration for email forwarding

IAM policy permissions edition

IAM policy permissions edition

IAM policy summary

IAM policy summary

4. Create a new email reception rule in Amazon SES

Again from the main page of the Amazon SES service, click on the Rule Sets menu option and then on the button Create a Receipt Rule, which will initiate a procedure of 4 very simple steps that will culminate with the creation of a new mail reception rule for your domain. The first of these steps will be to create one or more mail recipients. Here you can enter a single email address within your domain, or just the domain name to allow mail reception for any address.

Amazon SES receipt rule creation: step 0

Amazon SES receipt rule creation: step 0

Recipient creation for Amazon SES receipt rule

Recipient creation for Amazon SES receipt rule


Next create 2 actions that will be executed every time Amazon SES receives an email for your domain: store the message in an S3 bucket and then execute the Lambda function for it to be forwarded to your GMail account:

Amazon SES receipt rule action creation

Amazon SES receipt rule action creation

New S3 bucket creation

New S3 bucket creation

New S3 and Lambda actions created

New S3 and Lambda actions created

After completing these steps the mail reception rule is completely configured, but maybe it doesn’t become active and you have to go back and set it active. So once configured and activated if you send an email to the adress or addresses you created for your domain (in our example any address within the domain, ie you will see how the message is stored as a new object in the S3 bucket you just created when selecting the first action:

Receipt rule configured

Receipt rule configured

List of email messages as S3 bucket objects

List of email messages as S3 bucket objects

5. Verify your GMail address and create SMTP user

In order for Amazon SES to accept outgoing mail from your GMail account it is necessary to verify it and create an SMTP user:

Own domain email address verification

Own domain email address verification

Outgoing email SMTP configuration data

Outgoing email SMTP configuration data

SMTP user credentials created successfully

SMTP user credentials created successfully

Initially your newly configured Amazon SES service will be quarantined (sandboxed) by Amazon as a measure of protection against possible abuse and spam. To remove it from quarantine and allow normal mailing you need to open a support ticket to Amazon and fullfill a request. Otherwise you will see how the emails you send bounce with the following error message:

554 Message rejected: Email address is not verified. The following identities failed the check in region EU-WEST-1:

Below is the page from which you can request to be moved out of the sandbox and a request message example. In our example we asked for higher limits because we also want to use the Amazon SES service to send a weekly newsletter to our subscribers:

Sandbox warning and button to request sending limit increase

Sandbox warning and button to request sending limit increase

Example of Amazon support ticket to request moving out of sandbox and sending limit increase

Example of Amazon support ticket to request moving out of sandbox and sending limit increase

6. Configure GMail to send email from your domain’s addresses

We reached the final stretch. The only thing left is to configure GMail to send mail by putting your domain’s address as sender (From: field). In order to receive mail, nothing is to be done, as this is the responsibility of SES service and does not require any additional configuration. Between the two screenshots below there is an intermediate step that consists of entering the SMTP configuration data that was obtained in step #5:

How to add multiple email addresses to GMail

How to add multiple email addresses to GMail

GMail new address verification code

GMail new address verification code

7. Debugging and mail sending statistics

Finally, if something went wrong and you don’t get your emails properly redirected you can have error debugging information and log messages from your Lambda function provided by the CloudWatch service. You can also obtain email sending and receiving statistics from SES (see image from previous section #5) and operating statistics of your Lambda function as you can see below:

CloudWatch debugging and log messages

CloudWatch debugging and log messages

Forwarding email Lambda function statistics

Forwarding email Lambda function statistics


About the author

Daniel López Azaña
Freelance AWS Cloud Solution Architect & Linux Sysadmin

Entrepreneur, a generator of ideas and restless mind. Passionate about new technologies, especially Linux systems and Open Source Software. I also like to write about Technology News, Cloud Computing, AWS, DevOps, DevSecOps, System Security, Web Development and Programming, SEO, Science, Innovation, Entrepreneurship, etc.

DanielUse GMail with your own domain for free thanks to Amazon SES & Lambda

Related Posts


Join the conversation
  • Carlos Kynäslahti - 08/10/2017 reply


    Thanks for the instructions. Unfortunately, I could not get this to work. Earlier I was able to get emails to store in my bucket, but once the Lambda script was ran, it couldn’t get access to the bucket. I re-did everything, now my emails aren’t even stored inside the bucket, they bounce right back.

    These are the two issues I’m having:
    The “Step 3” IAM policy summary doesn’t list the “CloudWatch Logs” for some reason, even though I have the same configuration as you in the JSON. I’m getting this message in the policy Summary page: “This policy defines some actions, resources, or conditions that do not provide permissions. To grant access, policies must have an action that has an applicable resource or condition. For details, choose Show remaining”

    Another issue I ran into was with “Step 4”. After creating the bucket & lambda steps and hitting “Create Rule”, I get a message about “Missing Permissions”. My only option is to click “Add permissions”. Here is the whole message:

    “Missing Permissions

    SES was unable to access the resource arn:aws:lambda:eu-west-1:ID REMOVED HERE:function:carlospwk-email-lambda. It may not have the necessary permissions. Would you like SES to attempt to add those permissions on your behalf?
    SES will perform lambda:AddPermission with the following configurations:
    SourceAccount: MY ID HERE

    My only clue is that maybe something is not going according to plan when creating the Lambda function. I think the Lambda tool has been updated since this guide was written (the screenshot looks different).

    Sorry if this message seems basic, I’m new to Amazon AWS.

    Carlos Kynäslahti

  • Carlos Kynäslahti - 10/10/2017 reply

    I don’t see my previous message here, but in it I said I currently my emails bounce right back when I send something to SES. I noticed that even though I created a “Rule Set” in SES, it didn’t become active. I need to go back and set it active. After that it started working again. Consider adding a little notification about it in “Step 4”.

  • Carlos Kynäslahti - 10/10/2017 reply

    I _finally_ figured out what’s wrong with this. In “Step 3” there is the little config code snippet. The “emailKeyPrefix” variable no longer works if it’s just commented out. It should be empty like so: emailKeyPrefix: “”,. Once I fixed this, I started receiving email!

    Edgar Vazquez - 04/10/2020 reply

    Thank you! Not sure where I originally got that code snippet from, but it had the emailKeyPrefix filled out. Once I made it a blank string, I started getting the email into the bucket and forward to my gmail!

  • Daniel - 11/10/2017 reply

    I’m glad it’s working for you now! I’m sorry I couldn’t help you, but I’ve been so busy these days. Thanks for your feedback!

    Carlos Kynäslahti - 12/10/2017 reply

    Solving problems on your own is the best way to learn 🙂 Thank you for taking the time to write this guide!

  • Dan Rose - 06/12/2017 reply

    Works but not a great solution if you also want to receive mail that looks normal. Sending is flawless, but all mail received (SES forwarded on to my gmail account) shows up with correct reply-field only, but the From: field lists myself as the sender, instead of the original true sender. Huh? I’m the recipient not the sender. Apparently caused by the hack used to get SES to forward the mail in the first place.
    Not very usable if you want to receive email and reply quickly and not confuse the recipient, and or lose the customers email.

    Daniel - 19/12/2017 reply

    That’s true, but it’s not a problem for me as I know that emails from a given address (you can use an inexistent address from your domain, e. g. are actually forwarded emails and I only have to push the “Reply to” button to know the true sender’s address if the name, which is not modified, doesn’t give me a clue. From the sender’s point of view, nothing changes and it is completely transparent both when writing to us and when receiving mail from us, so I think it’s a great solution given the cost, and perfectly usable.

    Marbin - 13/01/2018 reply

    Hi Daniel. Thanks for all your help in this post. I just had one question. You mentioned that “From the sender’s point of view, nothing changes.” However, in my experience, when I reply to the sender, the sender sees that the origin of their email is now my own domain. As if I wrote their email. Is that the expected behavior or have I missed something?

    Daniel - 15/01/2018 reply

    Yes Marbin, I’m afraid it’s the expected behavior. You have to change the sender’s email address in the mail history below your response before you send it because although it’s name is displayed correctly, the email address is replaced by the forwarding address from your domain. I admit it’s a little annoying and you can forget about it. It is a flaw in this method, which is not perfect.

    Kristopher - 25/01/2019

    Wanted to mention that, as per this StackOverflow post, if you make the replyTo address one that is not configured in Gmail, it will revert to using the forwarded reply to address as desired. Hope this helps!

  • Suyash - 16/04/2018 reply

    Outstanding post. Better than all those docs on

  • Johnny - 15/07/2018 reply

    I was stuck attempting to do this until I found this post, thank you very much on writing it. You may want to edit the //emailKeyPrefix: “emailsPrefix/” part though as a previous poster has stated. That helped me fix ‘copyObject() returned error:’ that I was getting.

  • willie - 27/08/2018 reply

    Thanks for the post. I cannot figure out step 6. You posted two pictures, but not the middle step! What exactly are the STMP Server, Username and Password?
    I believe the STMP Server is the Amazon Server, but exactly which Username and password am I to use. I’ve tried so many, but all of them come back with “Authentication failed. Please check your username and password.”
    Help! This is making me crazy

    Daniel - 27/08/2018 reply

    “Between the two screenshots below there is an intermediate step that consists of entering the SMTP configuration data that was obtained in step #5”. Check again step #5, there is another screenshot with that username and password.

    Niels Horn - 05/01/2019 reply

    I had the same issue like you. First of all you have to add the domain to your google account!
    When you had verified, that the domain is yours, tha the step will succed

  • Willie - 04/09/2018 reply

    I retried today, following the same instructions that you provided. It worked. It must have been one of those things before, where I entered a typo, or was copy and pasting in a wrong field. Thank you for your thoughtful reply and thank you once again for this great article!!

  • David - 06/09/2018 reply

    Amazing post! Working like charm the very first time.

  • Michael OConnor - 11/09/2018 reply

    Very useful post. I set up a hosted domain with Route 53 last year but didn’t have mail (MX) support set up as I didn’t want to have yet another email service to worry about or pay for. This solved my problem and is up and running for me. Thanks!

  • Azat - 21/09/2018 reply

    I can not finish step 6. In the second figure, the code should come, but when I check the incoming to the mailing address … @ (this is the account to which I’m trying to attach … @ there is no letter. In general, even in spam(

    Juliana - 14/06/2019 reply

    The same happen with me 🙁

    Alberto - 12/08/2019 reply

    Please check if you manually created the MX record… I had the same problem and then after I double checked Route53 there wasn’t a MX there (please see last screenshot of step 2).

    Here’s some info on how do manually create that MX record but basically it’s adding as it is on the screenshot “10” where regionInboundUrl is the region that you configured SES e.g. (us-east-1 for US East (N. Virginia))

    By the way, thanks Daniel for such a complete guide!

  • Kraulain - 19/11/2018 reply

    Thanks very much for this.
    it works like charm.
    I was getting desperate and already considering paying for workmail which I consider greatly overpriced as compared to the service rendered. but this really helped me out

  • Abdul Hameed - 08/01/2019 reply

    I almost configured all things correctly but when adding Add a mail account step
    there are 3 inputs, username, password and POP Server. I entered STMP username and password which got from SES but what is POP Server. I tried default i.e “”, “” but nothing worked and last error is
    “There was a problem connecting to
    Server returned error: “Connection refused”
    any help will be greatly appreciated

    Daniel - 08/01/2019 reply

    Hi Abdul, a POP server is used to download messages from your mailbox into an email client such as Outlook, Thunderbird, etc. But there is no POP server involved in any of the steps of this post because the mail is sent and received through GMail using only the SMTP protocol and Amazon services mentioned, not downloaded using the POP protocol.

  • Shah - 10/01/2019 reply

    Dear Daniel

    This is a great article
    As you mention one or multiple ids can be used from same domain, Can you share info on how does it works when records are setup with cloudfare or other cdn as I am not sure will all records are affected or partial?

    Daniel - 14/01/2019 reply

    Only those records marked in red in step 2 are affected, and it doesn’t matter what the DNS provider is, because any of them must allow you to specify a record name, a record type and a value and they work in a similar way.

  • Kyle - 22/01/2019 reply

    thanks for the write up! worked like a charm 🙂

  • cheolgyu - 05/03/2019 reply

    thank you 😀

  • Sala - 04/04/2019 reply

    Thank you, now I have a .4$ email for my domain! There were two thing that didn’t work straight away though:

    1. Sending larger images(I tried over 3mb) failed. The issue was that the lambda function timeout was set to 3s. I guess it didn’t manage to send 3mb in 3s. I increased it to 3 min and now I can send larger images as well.

    2. To move out of the smtp sandbox it was required to manage bounces and complaints with SNS. Just sending them to my gmail was sufficient. Here is a tutorial:

  • Robert Christian - 29/04/2019 reply

    Seems like any DNS service can be used, doesn’t have to be Route 53. I’m already on Cloudflare, so I just used that. Everything works.

    Trying to figure out if it’s possible to do a rewrite of the raw text on all outgoing mail, to replace the From: address with the original sender’s address.

  • Robert Christian - 29/04/2019 reply

    I tried this and got it working, but I wasn’t happy with the From: address being rewritten to, so I found an alternative that’s actually easier. For all incoming mail, forwards to gmail or any other personal email address. For all outgoing mail, I use SES, like in the above setup.

  • Juliana - 14/06/2019 reply

    Hi you all,
    I’m having this error in lambda function:

    “errorType”: “Runtime.ImportModuleError”,
    “errorMessage”: “Error: Cannot find module ‘streetdogspt-com-forwarding'”,
    “trace”: [
    “Runtime.ImportModuleError: Error: Cannot find module ‘streetdogspt-com-forwarding'”,
    ” at _loadUserApp (/var/runtime/UserFunction.js:100:13)”,
    ” at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)”,
    ” at Object. (/var/runtime/index.js:36:30)”,
    ” at Module._compile (internal/modules/cjs/loader.js:701:30)”,
    ” at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)”,
    ” at Module.load (internal/modules/cjs/loader.js:600:32)”,
    ” at tryModuleLoad (internal/modules/cjs/loader.js:539:12)”,
    ” at Function.Module._load (internal/modules/cjs/loader.js:531:3)”,
    ” at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)”,
    ” at startup (internal/bootstrap/node.js:283:19)”

    I’m new at this, can you help me?

    Thank you very much!

  • Sebastian - 27/08/2019 reply

    You saved me a whole lot of trouble with this guide!
    There is very little about actual configuration of Lambda forwarder (fortunately this lambda got inline explanation in code) and it’s worth noting you should first create S3 bucket to then use as I think it wasn’t stated anywhere.

    Nevertheless, awesome guide!

  • willie - 10/09/2019 reply

    Mr. Daniloaz,
    First, thanks again for your post and replies to all these questions. I have tried to verify a second gmail account to send emails as an alias, but I am not able to. I know that the credentials are correct, because I established another alias on my original gmail, w*****.w*****, but I cannot set up another gmail to send under aliases with these same credentials. I am sure there is something I’m misunderstanding about the SMTP format.
    Any explanation would really help.

  • Richard - 10/12/2019 reply

    Awesome resource. If I may, you should just update the article with this emailKeyPrefix, I went through researching while it was in the comments.
    Plus the Gmail screenshot in English and this piece will be a master class

  • Henry - 06/04/2020 reply

    Is there an easy way to filter given domains? I’ve been flooded with spam. I cannot use gmail spam filters since the sender is always myself.

  • Shinoj - 16/06/2020 reply

    Hi there,
    I am using office 365 server as my SMTP, need to work with aws lambda. While triggering the function, i am getting error. Can I use office365 as SMTP in aws ~

  • Cael - 31/08/2021 reply

    Great guide!
    Still working perfectly, considering you have to change the emailKeyPrefix param to “”, instead of commenting out the whole line.

Leave a Reply

Your email address will not be published.