3

I already have code for sending e-mails with python:

def send_email_gmail(subject, message, destination):
    """ Send an e-mail using gmail with message to destination email.

    Arguments:
        message {str} -- message string to send.
        destination {str} -- destination email (as string)
    """
    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    # not a real email account nor password, its all ok!
    server.login('me123@gmail.com', 'fakepassword111!!!')

    # craft message
    msg = EmailMessage()

    message = f'{message}\n'
    msg.set_content(message)
    msg['Subject'] = subject
    msg['From'] = 'me123@gmail.com'
    msg['To'] = destination
    # send msg
    server.send_message(msg)

and I've read the multiple question (Login credentials not working with Gmail SMTP or SMTPAuthenticationError when sending mail using gmail and python) solving the common error:

smtplib.SMTPAuthenticationError: (534, b'5.7.14 <https://accounts.google.com/signin/continue?sadfdgjsfgrp=1&dsfgscc=1dsdfgsfg&pldsfgt=AKsdfsdfggsdfggnsbu\n5.7.14 G0crCr0qSvWTng9xRE_pd3WnK3S2sDMsdfgsdfgX0J-xoetn7aHyFQi2qYrQisdfgsdfgKIwMCcgD7zLB1t7Z\n5.7.14 -OjHjpJqasdftBuTi9wh0sYlNW637SmPLuMnnLGn_WcZX5TGH4sddsfgXYar-Aasdfw0ctWfLhasdffPQV>\n5.7.14 Please log in via your web browser and then try again.\n5.7.14  Learn more at\n5.7.14  https://support.google.com/mail/answer/787521345364524 n21sm17577sadfdsf46qtn.17 - gsmtp')

Anyway, I did what those answers suggest but I am still getting an error. So I decided I do not want to use gmail anymore for this. I am sending email from a fake account just for sending emails so the security for it doesn't matter to me.

So how do change the code above so that it works for a different emailing service that is more reliable for sending emails in python/code?

The idea answer would contain be self contained and contain a sample script that works.


Edit1:

I've of course check to turn on less secure app feature on my fake gmail, copy paste text of what that page says:

Turn off less secure app access
Your account is vulnerable to malicious activity because you’re allowing apps & devices that use less secure sign-in technology to access your account. You should turn off this type of access. Google will automatically turn this setting OFF if it’s not being used. Learn more

there is also a yellow exclamation sign warning me.


Edit2

Output of EmailMessage():


it as suggested I paste this (empty message).

Charlie Parker
  • 5,884
  • 57
  • 198
  • 323
  • 2
    Choose another SMTP server you have credentials for, and point smtplib at it. Or preferably use some non-SMTP email gateway like sendgrid, mailgun, mailjet, ... – AKX Apr 01 '20 at 16:17
  • 1
    This website has a list of servers and their ports: https://www.arclab.com/en/kb/email/list-of-smtp-and-pop3-servers-mailserver-list.html – Thomas Brefeld Apr 01 '20 at 16:28
  • Sorry I am not an expert on this, but I don't know what having credentials for a server means. I have credentials for fake email address I can create for sending e-mails. Is that enough or do I have to do something else? I don't care what I use, gmail or whatever, as long as it always sends e-mails and it's not a pain. – Charlie Parker Apr 01 '20 at 16:39
  • @ThomasBrefeld I am not an expert in this. I don't know how to use that list you sent me to change my script. Any ideas/help? – Charlie Parker Apr 01 '20 at 16:40
  • @Pinocchio I've used google's SMTP server a few years back and it worked well. I remember I had a lot of issues until I allowed less secure apps with the account and after that everything seemed to work. I'm sure you've tried this, but can you make sure the account allows less secure apps. could you also post "EmailMessage()" or just what it returns? – Thomas Brefeld Apr 01 '20 at 17:23
  • @ThomasBrefeld makes sense to request me to check that. I have of course checked it. This is what the output of the browser is when it's off (plus there is a yellow exclamation mark warning me of this `Turn off less secure app access Your account is vulnerable to malicious activity because you’re allowing apps & devices that use less secure sign-in technology to access your account. You should turn off this type of access. Google will automatically turn this setting OFF if it’s not being used. Learn more`. For the output of `EmailMessage()` I will do in a sec. Is that just a python command? – Charlie Parker Apr 01 '20 at 17:27
  • @ThomasBrefeld note thomas that for me to print the output of `EmailMessage()` I have to comment out the login attempt code right before it (see the code in my question). Regardless, this is it's output: ` ` once I comment that out (empty message). Is that what you expected? – Charlie Parker Apr 01 '20 at 17:33
  • @Pinocchio I'm still working on trying to get my code to run through this, but have you tried resigning into the account on your web browser and then within 10 minutes launch your code again. – Thomas Brefeld Apr 01 '20 at 18:34
  • @ThomasBrefeld any progress? May help you with something? – Charlie Parker Apr 02 '20 at 13:17
  • @ThomasBrefeld I didn't get around checking your answer but I saw you deleted it. Why? Does it not work? I will try it now. – Charlie Parker Apr 05 '20 at 19:48
  • @ThomasBrefeld I tried your "Also under "Signing in to Google" Select "App passwords"." but I can't click on Signing in to Google... did u have that issue? – Charlie Parker Apr 05 '20 at 19:59
  • @ThomasBrefeld that seems to work! Return your answer! :D – Charlie Parker Apr 05 '20 at 20:09
  • @Pinocchio Glad to hear it work, I removed my post because I noticed you titled the issue 'NOT using Gmail' so I figured you wouldn't want my answer. – Thomas Brefeld Apr 06 '20 at 01:01
  • @ThomasBrefeld i think u should leave it :) – Charlie Parker Apr 06 '20 at 01:02
  • @Pinocchio I readded the solution back since it helped you, it might help someone else. – Thomas Brefeld Apr 06 '20 at 21:35
  • @Pinocchio have you check that the ports that you use for sending mails (outgoing) are open on Windows FW and Router FW. Can you establish a telnet connection with that port? – furkanayd Apr 09 '20 at 17:55

5 Answers5

10

I found the most reliable way to connect to google's SMTP server is via an app password.


How to get an app password

  1. go to manage my google account
  2. Under "Signing in to Google" confirm that "2-Step Verification" is "On" for the account.
  3. Also under "Signing in to Google" Select "App passwords".
  4. Select the app as "Mail" and the device as "Other (Custom name)" and name it.
  5. Copy the app password, it will be in a yellow box and looks like: "XXXX XXXX XXXX XXXX"

Using the app password in your code

import smtplib
from email.message import EmailMessage

def send_email_gmail(subject, message, destination):
    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    #This is where you would replace your password with the app password
    server.login('account@gmail.com', 'App_Password')

    msg = EmailMessage()

    message = f'{message}\n'
    msg.set_content(message)
    msg['Subject'] = subject
    msg['From'] = 'me123@gmail.com'
    msg['To'] = destination
    server.send_message(msg)

send_email_gmail('Test subject', 'This is the message', 'to_email@email.com')

Hope this helps!

Thomas Brefeld
  • 311
  • 2
  • 13
  • 1
    Great answer. Amazing, it worked on the first try! – james Jul 16 '22 at 11:31
  • I don't see "App passwords" available on that page anymore. I think gmail disabled this – cxrodgers Mar 29 '23 at 02:01
  • Update: this does still work! I had to go back to "2-step verification" settings again, and app passwords was hidden under there, rather than listed under "Signing into google" as in the original answer – cxrodgers Apr 02 '23 at 20:58
2

For me it works like expected when I login using SSL, like so:

import smtplib, ssl
from email.mime.text import MIMEText


def send_email_gmail(subject, message, destination):
    # First assemble the message
    msg = MIMEText(message, 'plain')
    msg['Subject'] = subject

    # Login and send the message
    port = 465
    my_mail = 'me123@gmail.com'
    my_password = 'fakepassword111!!!'
    context = ssl.create_default_context() 
    with smtplib.SMTP_SSL('smtp.gmail.com', port, context=context) as server:
        server.login(my_mail, my_password)
        server.sendmail(my_mail, destination, msg.as_string())


send_email_gmail('Test subject', 'This is the message', 'to_email@email.com')

EDIT:

However, if you would really like to use another smtp server you could use outlook for instance. I got this to work without SSL, by connecting to smtp-mail.outlook.com on port 587, like so:

def send_email_gmail(subject, message, destination):
    # First assemble the message
    msg = MIMEText(message, 'plain')
    msg['Subject'] = subject

    # Login and send the message
    port = 587
    my_mail = 'my_mail@hotmail.com'
    my_password = 'my_password'
    with smtplib.SMTP('smtp-mail.outlook.com', port) as server:
        server.starttls()
        server.login(my_mail, my_password)
        server.sendmail(my_mail, destination, msg.as_string())

send_email_gmail('Test', 'Bericht', 'm.drillenburg@gmail.com')
1

I have a function I use to send emails through yahoo. You don't need to pip install anything either.

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText


def send_email(subject, to_email, message):
    password = "some_password"  # needs to be changed
    my_email = "some_email@yahoo.com"  # needs to be changed
    smtp_obj = smtplib.SMTP('smtp.mail.yahoo.com', 587)
    smtp_obj.starttls()
    smtp_obj.ehlo()
    smtp_obj.login(my_email, password)
    msg = MIMEMultipart()
    msg['From'] = my_email
    msg['To'] = to_email
    msg['Subject'] = subject
    msg.attach(MIMEText(message, 'plain'))
    smtp_obj.sendmail(msg['From'], msg['To'], msg.as_string())
    smtp_obj.quit()


if __name__ == '__main__':
    send_email('Subject: Automated e-mail', 'my_test_email@test.com', 'This was sent via script')

This is obviously the most basic format for an email with nothing more than a subject and body, but there is much more you can do. If you'd like to get more advanced read through the email and smtplib documentation from the standard library.

Reedinationer
  • 5,661
  • 1
  • 12
  • 33
0

An advice to switch to another provider if you are not satisfied with the service provided by gmail is not complete without exploring other options.

You could send the message directly to the destination email server on TCP port 25. An SMTP server should accept a message for the "own" domain from any client without any authorization required. No problems with credentials here.

The address of that server can be obtained from DNS by looking up MX records (MX stands for mail exchanger) for the recipients's email domain. Usually there are several of them. The MX hosts have preferences (lowest number = highest preference) and for best results they should be contacted in the order from highest preference to the lowest until a mail is accepted.

The downsize is that you have to take care of retries if the first attempt fails - a mail queue is usually used for that purpose. Some sites use "graylisting" where the first attempt will fail as an anti-spam measure.

All that becomes less trival when there are multiple recipients in a message and such program becomes a tiny subset of a real SMTP server. You might even want to install a real server like Linux "postfix" and configure it send-only, there are tutorials available. Just be aware, that there are tons of configuration options.

VPfB
  • 14,927
  • 6
  • 41
  • 75
  • I just want a python script that is easy to use and works...how do I change the configurations so that I don't use google as you suggested. Do you have sample code? – Charlie Parker Apr 05 '20 at 19:49
  • A simple script is just a client requesting a server to send a message. You must start with selecting the server. When you reach an agreement that you are permitted to use some particular server, you'll be given its address, your login and a password. Replace the gmail's data with those new data. Do not expect to find a free server you can use without an account. – VPfB Apr 06 '20 at 08:51
0

If you just want another email address, find the SMTP of your new email server.

server = smtplib.SMTP('smtp.newemail.com', port)
# replace the url and port with your new server's smtp.

The rest should be the same