Deconfusing How To Use Gmail's SMTP server in 2024

5 min read

I'm old enough to remember when writing an app to send emails from a Gmail account was cool. You click a couple things in your Google account console, you provide your username and password to your app, and zing, you're in business.

Now, in 2024, this process is not as simple as it used to be—which means that it's definitely not as cool.

Today I'm gonna show you exactly how you can make apps that send emails from your Gmail account, while avoiding some of the gotchas waiting for you during this process—most of which stem from Google's confusing, poorly documented, security console.

The app code

For simplicity, we're gonna use the following go snippet, borrowed from a wonderful blog source, and use it as our sample application code.

package main

import (
  "fmt"
  "net/smtp"
  "flag"
)

var username = flag.String("username", "", "gmail email address")
var password = flag.String("password", "", "gmail password")
var to = flag.String("to", "", "address receiving email")

func main() {
  flag.Parse()

  if *username == "" {
    panic("no username")
  }

  if *password == "" {
    panic("no password")
  }

  if *to == "" {
    panic("no to address")
  }

  // Receiver email addresses.
  rcvs := []string{
    *to,
  }

  // smtp server configuration.
  smtpHost := "smtp.gmail.com"
  smtpPort := "587"

  // Message.
  message := []byte("This is a test email message.")
  
  // Authentication.
  auth := smtp.PlainAuth("", *username, *password, smtpHost)
  
  // Sending email.
  err := smtp.SendMail(smtpHost+":"+smtpPort, auth, *username, rcvs, message)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println("Email Sent Successfully!")
}

This code is extremely simple. When we run it, it should send an email with the message "This is a test email message." to the --to address we provide.

Sending emails from your personal Gmail account

If you want to send emails from your personal Google account, your first step should be signing into your google account where you'll need to create an "App Password". This password will be used by the app code to send emails from your Gmail account.

Unfortunately, there's no way (that I've found) to be able to click your way to the "App Passwords" page using the console for a personal Gmail account.

For Google Workspaces or teams, you can find app passwords by clicking "Security" in the left side navigation bar, then clicking "2-step Verification" in the center of the page. "App Passwords" is usually found here. (You will probably need to set up 2-step verification on your Google account before continuing on, by the way).

But, for personal Google accounts, at least for me, "App Passwords" is not here.

No app passwords section

Instead, you need to search for "App Passwords" in the console search bar in order to find it, like so.

Search personal app passwords

Once you find the "App Passwords" page, you need to generate a new app password.

App Passwords page

Let's create an app password called my-app.

App Password my-app

After we collect our newly generated app password that we should be able to supply as the password to our app, and successfully send an email.

ubuntu@ip-10-2-0-238:~/email_app$ ./email_app --username dustin@gmail.com --password "nkzh pnky qppz jtjw" --to dustin@dolthub.com
535 5.7.8 Username and Password not accepted. For more information, go to
5.7.8  https://support.google.com/mail/?p=BadCredentials gq13-20020a17090b104d00b002ad059491f6sm1779187pjb.5 - gsmtp

And we get denied.

Luckily, Gmail provides a url for us in the error message that... won't help us at all. It's actually full of irrelevant links for plebs.

Instead, the way to fix this is to simply generate a new app password, and try that one. We'll call this new one my-app-2.

App Password my-app-2

And of course the new password works as expected.

ubuntu@ip-10-2-0-238:~/email_app$ ./email_app --username dustin@gmail.com --password "pujx hhsi sdsu ewfz" --to dustin@dolthub.com
Email Sent Successfully!

Why does the second password work and not the first? Why? Because fuck you, that's why.

Now you might be thinking that the reason the first app password we generated didn't work was because we needed to use the Google console to verify that it was us who created the app password in the first (even though we didn't need to verify anything to get the second app password to work). Maybe this is just some additional security measure implemented by Google.

So, if we go back to the "Security" page, we can see the app passwords we created in our "Recent security activity".

Recent security activity

And, if we click our app password my-app that doesn't work, we can see Google wants us to verify that we in fact made the password.

Verify that it was us

So, after clicking "Yes, it was me", I tried our first app password again.

ubuntu@ip-10-2-0-238:~/email_app$ ./email_app --username dustin@gmail.com --password "nkzh pnky qppz jtjw" --to dustin@dolthub.com
535 5.7.8 Username and Password not accepted. For more information, go to
5.7.8  https://support.google.com/mail/?p=BadCredentials n7-20020a170902e54700b001eb3dadacffsm1853286plf.219 - gsmtp

And, once again, we're denied.

So the lesson here, I guess, is to always generate an additional app password in order get your apps to send emails from your personal Gmail account, cause something on Google's side is kinda fucky.

Sending emails from your Gmail team account/Google Workspaces

Now let's see if we can get our app working for a Google Workspaces account, which you might use for your entire team, like we do here at DoltHub.com for our dolthub.com email addresses.

We're going to follow the same process we used above.

First, we sign-in to our Gmail team account, navigate to our account page, and click the "Security" section in the left navigation section.

Now, if we click "2-step Verification" (that you should set up before continuing on), and scroll down, we see "App Passwords" this time.

Now app passwords can be viewed from the 2-step page

Like before, we create a new app password called my-app, copy the generated password, and supply it to our email app.

Team account app password

ubuntu@ip-10-2-0-238:~/email_app$ ./email_app --username dustin@dolthub.com --password "vzuo vgth vqsq kebz" --to dustin@gmail.com
Email Sent Successfully!

And... it appears it works the first time? So... that's good, I suppose.

I also tried generating an additional app password and using that one. It also worked. Maybe team Google accounts get preferential app passwords or something that the free-loading, personal-account-having-ass-gmailers, like me, can't get.

My teammates weren't so lucky. The reason I'm writing this blog is because yesterday, two people on the team could not get their App Passwords using a dolthub.com email address to work testing DoltLab, our self-deployed collaboration platform. It was strange because the App Password would work from a simple script but not from the website backend.

The lesson here I guess is App Password is unreliable so keep trying until one works. This seems like a poor solution from Gmail at this point. I hope this blog catches the attention of the team in charge of this at Google HQ and something gets fixed.

Conclusion

In conclusion, I thought about one more reason why this sometimes works and sometimes doesn't. I thought maybe some asynchronous process on the Gmail SMTP server side just needed a bit more time to accept/validate the original app password I created for my personal Gmail account. Maybe I just didn't wait long enough for this process to complete before I tried to using the password.

So, after waiting about 30 minutes, I tried using it again.

ubuntu@ip-10-2-0-238:~/email_app$ ./email_app --username dustin@gmail.com --password "nkzh pnky qppz jtjw" --to dustin@dolthub.com
535 5.7.8 Username and Password not accepted. For more information, go to
5.7.8  https://support.google.com/mail/?p=BadCredentials jo3-20020a170903054300b001e904b1d164sm1897770plb.177 - gsmtp

Ugh.

Anyway, I hope this blog saves you from having to debug things that are really just the Gmail SMTP server misbehaving. If you know more information about what's going on with Gmail, or know of a better way to do the above, swing by our Discord.

Thanks for reading and don't forget to check out each of our cool products below:

SHARE

JOIN THE DATA EVOLUTION

Get started with Dolt

Or join our mailing list to get product updates.