54

Using python I want to send email from my app but it shows the error

SMTP AUTH extension not supported by server

Code for the program,

import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
fromaddr = "test1@example.com"
toaddr = "test2@example.com"
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "Test Mail"
body = "Test mail from python"
msg.attach(MIMEText(body, 'plain'))
server = smtplib.SMTP('smtp.example.com', 25)
server.ehlo()
server.starttls()
server.ehlo()
server.login(fromaddr, "password")
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()

Telnet Output:

ehlo test1.example.com
250-hidden
250-HELP
250-SIZE 104857600
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-STARTTLS
250 OK

I need to authenticate and send mail from app.

KKD
  • 708
  • 1
  • 6
  • 15
  • In my case, uncommenting the lines EMAIL_HOST_USER and EMAIL_HOST_PASSWORD and setting both variables to an empty string was enough. I'm using Taiga6 with an unauthenticated SMTP server. – Marcello Aug 30 '22 at 08:07

6 Answers6

80

a connection is required before login and sendemail.

server = smtplib.SMTP('smtp.example.com', 25)
server.connect("smtp.example.com",465)
server.ehlo()
server.starttls()
server.ehlo()
server.login(fromaddr, "password")
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()
Kris
  • 1,618
  • 1
  • 13
  • 13
  • 1
    After establised the connection `server.connect` it worked fine. Thanks! – KKD Nov 11 '16 at 07:32
  • 4
    Port 465 is for SMTPS. If you are not providing any port, it defaults to 25. SSL encryption is started automatically before any SMTP level communication when using SMTPS. – Kris Sep 29 '17 at 08:29
  • According to the official documentation, connect() is called implicitely. – Federico Jun 01 '19 at 18:02
  • 1
    can you please explain, why 'server.ehlo()' is needed two times? – naiz0 Jul 09 '22 at 17:06
41

There is no need to call smtp.connect() and smtp.ehlo(), because they are called automatically by SMTP() and smtp.starttls(). The issue is solved simply setting port to 587 instead of 28.

For client use, if you don’t have any special requirements for your security policy, it is highly recommended that you use the create_default_context() function to create your SSL context. It will load the system’s trusted CA certificates, enable certificate validation and hostname checking, and try to choose reasonably secure protocol and cipher settings.

In general, you will want to use the email package’s features to construct an email message, which you can then send via send_message().

import smtplib, ssl
from email.message import EmailMessage

msg = EmailMessage()
msg.set_content("The body of the email is here")
msg["Subject"] = "An Email Alert"
msg["From"] = "me@example.com"
msg["To"] = "you@example.com"

context=ssl.create_default_context()

with smtplib.SMTP("smtp.example.com", port=587) as smtp:
    smtp.starttls(context=context)
    smtp.login(msg["From"], "p@55w0rd")
    smtp.send_message(msg)
Asaga
  • 591
  • 4
  • 6
  • 1
    Thanks, this solves my problem in the most elegant way. This answer deserves higher ranking. – Alkhwarizmi Jun 10 '20 at 16:10
  • TLS protocols 1.0 and 1.1 are being deprecated in most places. If anyone wants to enforce TLSv1.2, here is the way to do it: context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) – Baurito Sep 30 '22 at 15:32
9

It is probably just the server I was using, but was getting the same error as the OP even after implementing the accepted solution. Turned out the server did not want a login, so after deleting the line server.login(fromaddr, "password"), the error went away and it worked.

cardamom
  • 6,873
  • 11
  • 48
  • 102
1
import smtplib

s = smtplib.SMTP('smtplib.gmail.com',587)
s.ehlo()
s.starttls()
s.login('frmaddr','password')
try:
    s.sendmail('fromaddr','toaddr','message')
except:
    print (failed)
Alireza HI
  • 1,873
  • 1
  • 12
  • 20
  • 9
    Welcome to Stack Overflow! While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Suraj Rao May 17 '19 at 07:56
  • 3
    `print (failed)` would throw an exception since failed is an undeclared variable in this case. I guess you forgot to add the quotes around 'failed'. – Patrick Klein Oct 18 '20 at 16:36
1

The first tap is enable your gmail account to send emails by another applications, allow in this section:

https://myaccount.google.com/lesssecureapps

Then, you should can to send an email

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

msg = MIMEMultipart()
message = "This is an email"

password = "yourpasswordemailsender"
msg['From'] = "emailsender@gmail.com"
msg['To'] = "emailsended@gmail.com"
msg['Subject'] = "Title of email"

msg.attach(MIMEText(message, 'plain'))
server = smtplib.SMTP('smtp.gmail.com: 587')
server.starttls()
server.login(msg['From'], password)
server.sendmail(msg['From'], msg['To'], msg.as_string())
server.quit()
qarly_blue
  • 380
  • 3
  • 7
1

you need to 'starttls' before login.

Benchur Wong
  • 2,377
  • 2
  • 9
  • 13