New to Python, GMail SMTP error - python

I am writing a simple sendmail function to myself and I keep getting this error:
NameError: name 'SMTPException' is not defined
What is wrong with my code? Any suggestions?
import smtplib
sender = "user#gmail.com"
receiver = ["user#gmail.com"]
message = "Hello!"
try:
session = smptlib.SMTP('smtp.gmail.com',587)
session.ehlo()
session.starttls()
session.ehlo()
session.login(sender,'password')
session.sendmail(sender,receiver,message)
session.quit()
except SMTPException:
print('Error')

In Python, you will need to fully qualify the name by prefixing it with its module:
except smtplib.SMTPException:
This is true unless you specifically import the unqualified name (but I wouldn't recommend doing this for your program, just showing what's possible):
from smtplib import SMTPException

That misspelling occurred many times to me as well! One way to circumvent this "problem", is to use yagmail.
Jokes aside, I recently created yagmail to make it easier to send emails.
For example:
import yagmail
yag = yagmail.SMTP('user#gmail.com', 'password')
yag.send(contents = "Hello!")
It uses several shortenings here, for example when To is not defined, it will send a mail to the same email who registered on the server. Also the port and host are the default, which makes it very concise.
In fact, since it seems you want to close the connection immediately, you can even use this one-liner:
yagmail.SMTP('user#gmail.com', 'password').send(contents = "Hello!")
For security, you can keep your password in the keyring (see documentation) such that you do not have to keep your personal password in your scripts, very important! It'll even save you more precious screen-estate.
Going all-in with the package (#gmail.com is default), you can get away with the following:
yagmail.SMTP('user').send('', 'Hello!')
Good luck.

from smtplib import SMTPExeption
exep smtplib.SMTPExeption

Related

Send email in Python [duplicate]

This question already has answers here:
How to send an email with Gmail as provider using Python?
(16 answers)
Closed last month.
Now, as the Lesser secure apps feature in Gmail has been disabled, I am trying to find alternatives for email sending. I am trying freemail.hu as an alternative which supports SMTP protocol, but any other suggestion is highly welcome.
According to the web page, the data for SMTP are the following:
Server name: smtp.freemail.hu
Port: 587 (with STARTTLS)
Username: email address
Password: the same as used on the web
My code looks like this:
import smtplib
import ssl
try:
server = smtplib.SMTP('smtp.freemail.hu', 587)
server.starttls(context=ssl.create_default_context())
server.login('[myuser]#freemail.hu', '[mypassword]')
server.sendmail('[myuser]#freemail.hu', ['[myprivatemail]#gmail.com'], 'Test mail.')
except Exception as e:
print(e)
finally:
server.quit()
The username is password is correct: I checked them several times + it works on the web interface. However, I am getting the following error message:
(535, b'5.7.8 Error: authentication failed: [encoded value]')
Does anyone has an idea what the problem could be?
I tried two email providers (freemail.hu, mail.com), tried to log in with and without server name, tried to enter the password from command prompt, checked the settings looking for the feature similar to Lesser secure apps in Google, but nothing helped.
For Gmail the App Passwords as described on page https://support.google.com/mail/answer/185833 works well. The 2 step verification should be turned on, and then a 16 character long random password can be generated on the App passwords section.
Every tried ofunctions.mail package ?
Deals with ssl and tls, attachments, encoding, etc.
Install with pip install ofunctions.mailer
Usage
from ofunctions.mailer import Mailer
recipients = ['me#example.com', 'them#example.com', 'anyone#example.com', 'malformed_address_at_example.com']
mailer = Mailer(smtp_server='mail.example.com', smtp_port=465, security='ssl', debug=True, verify_certificates=False)
# split_mails=True will send one email per recipient
# split_mails=False will send one email for all recipients, which will be limited to the number of recipients the destination SMTP server allows
mailer.send_email(subject='test', sender_mail='me#example.com', recipient_mails=recipients, body='some body just told me', split_mails=True)
Just replace ssl with tls or None if needed.
See more usecases at github
disclaimer: I'm the author of ofunctions package.

How to store a password in my python script but have it obscured from any users when deployed to Github?

I've been trying to work this one out for a while now but keep finding imperfect solutions - I think what I want to do is possible but maybe I'm not phrasing my Google search correctly.
I have a Python script that sends a user an email notification - in order to send said email I need to provide a password in the script to send the email. The code works perfectly but it requires that I pass the password into the script:
def send_email():
import smtplib
import ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
sender_email = "my-generic-email#gmail.com"
receiver_email = "recipient#gmail.com"
password = "my_password_here"
message = MIMEMultipart("alternative")
message["Subject"] = "subject_here"
message["From"] = sender_email
message["To"] = receiver_email
# Create the plain-text and HTML version of your message
text = f"""\
Plain text body here
"""
# Create secure connection with server and send email
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login(sender_email, password)
server.sendmail(
sender_email, receiver_email, message.as_string()
)
I don't want to store the password as plain text for obvious reasons. I've thought of environment variables but this wouldn't work as this is going to be deployed on GitHub for other people to use (or install as an EXE) so this would break the email functionality.
I've tried looking at PyCryptodome but anything I've found so far suggests encrypting the password with a key but then storing the key in the script to decrypt the password when you use it. This seems like a bad idea to me as surely any novice (like me!) would be able to easily decrypt this because the key is stored in the script.
Is anyone able to help push me in the right direction? I'm completely out of ideas as frankly I know hardly anything about password storing/security so not even sure what I should be Googling!
If others have to use your password to be able to use your script, it's impossible. If the computer can read it, then the user will also find a way to read it.
I recommend using a E-Mail service where the user can enter their own API key or just let them enter their own GMail credentials.
Correct me if I'm wrong, but I think there's no way to use your password in this case unless you write an API and send the E-Mail from your server. But don't forget that in this case, the user might be able to use your API as a way to send spam.
TL;DR: Let the users use their own passwords.

Python reading email from outlook account using imaplib/imapclient vs exchangelib?

I am setting up a script to read incoming emails from an outlook.com account and I've tested a few approaches with imaplib and was unsuccessful. Yet when I tried with Exchangelib I was able to do this. I'm not entirely sure why Exchangelib works and imaplib doesn't. I feel like I might be breaking some best practices here as I don't know how Exchangelib is able to connect to the mailbox through some sort of trickery of network connections?
For reference the IMAP code that doesn't work (though it works when I attempt to connect to my personal gmail account)
from imapclient import IMAPClient
import mailparser
with IMAPClient('outlook.office365.com', ssl=True) as server:
server.login("username", "password")
server.select_folder('INBOX')
messages = server.search(['FROM', ])
# for each unseen email in the inbox
for uid, message_data in server.fetch(messages, 'RFC822').items():
email_message = mailparser.parse_from_string(message_data[b'RFC822'])
print("email ", email_message)
I get the below error
imapclient.exceptions.LoginError: b'LOGIN failed.'
When I use exchangelib it works succesfully. Reference code below:
from exchangelib import Credentials, Account
credentials = Credentials("username", "password")
account = Account(username, credentials=credentials, autodiscover=True)
for item in account.inbox.all().order_by('-datetime_received')[:100]:
print(item.subject, item.sender, item.datetime_received)
Is there any reason why I can't connect with imaplib/imapclient vs exchangelib? Perhaps some security related reason that I'm not aware of?
I think you might need to pass in the full email-ID when using imapclient/imaplib vs just the username when using exchangelib.

Python login to email server authentication error

I am on a Linux machine. My company has an email exchange server which is already configured. I am using a Python script to try to login to the email server so that I can send an email programmatically. Here is what I have so far -
server = smtplib.SMTP('email-0.abc.com', 25)
server.set_debuglevel(1)
server.ehlo_or_helo_if_needed()
server.login('abc/johndoe', 'pwd')
However, at the server.login command, I get an error as
raise SMTPException("No suitable authentication method found.")
SMTPException: No suitable authentication method found.
Anyone know what the problem is please?
Thanks
You might need to switch to STARTTLS authentication. Here's an example that helped me.
How To Send Email In Python Via SMTPLIB
It seems that your Mail Server is rejecting the plain Authentication method.
What server do you use?
If MS Exchange please see this article: http://www.exchangeinbox.com/article.aspx?i=93
I was getting the same error. My case could be the different from yours but error is same as you mentioned.
In my scenario, I don't have to pass the username and password for authentication as server IP was added in white-list of SMTP mail server. And I was passing username and password for authentication which was giving me the error stating "No suitable authentication method found."
This may not be the case with you but I just thought to share the my experience for the same kind of error so that anyone coming to this thread can benefit from it.
Thanks.
The Exchange server I was connecting to, required NTLM authentication, which is not supported by smtplib out of the box.
As of this writing (January 2022) and according to my modest research, the most maintained Python library that solves this problem, is pyspnego. The following snippet was provided by the library author and worked for me without any modifications:
import base64
import spnego
from smtplib import SMTPException, SMTPAuthenticationError
def ntlm_authenticate(smtp, username, password):
auth = spnego.client(username, password, service="SMTP", protocol="ntlm")
ntlm_negotiate = auth.step()
code, response = smtp.docmd("AUTH", "NTLM " + base64.b64encode(ntlm_negotiate).decode())
if code != 334:
raise SMTPException("Server did not respond as expected to NTLM negotiate message")
ntlm_challenge = base64.b64decode(response)
ntlm_auth = auth.step(ntlm_challenge)
code, response = smtp.docmd("", base64.b64encode(ntlm_auth).decode())
if code != 235:
raise SMTPAuthenticationError(code, response)

Django sending email

In PHP I can send an email simply by calling mail(). In Django, I need to specify SMTP backends and other things.
Is there a simpler way to send email from Django?
There are several good mail-sending functions in the django.core.mail module.
For a tutorial please see Sending e-mail:
Although Python makes sending e-mail
relatively easy via the smtplib
library, Django provides a couple of
light wrappers over it. These wrappers
are provided to make sending e-mail
extra quick, to make it easy to test
e-mail sending during development, and
to provide support for platforms that
can’t use SMTP.
The simplest function that would most likely suit your purposes is the send_mail function:
send_mail(
subject,
message,
from_email,
recipient_list,
fail_silently=False,
auth_user=None,
auth_password=None,
connection=None)
In PHP you can only send mail with a simple mail() command on non-Windows systems. These will expect a local MTA like Postfix to be installed and correctly configured, as should be the case for most web servers. If you want to depend on third-party or decentralized mail service depends on how critical email is for your application. Serious dependency on speedy and reliable email transmission usually results in sending mail via SMTP to a central mail server (the "big pipe").
Still, if you want to have the same function as in PHP, try this:
import subprocess
def send_mail(from_addr, to_addr, subject, body):
cmdline = ["/usr/sbin/sendmail", "-f"]
cmdline.append(from_addr)
cmdline.append(to_addr)
mailer = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
dialog = "From: %s\nTo: %s\nSubject: %s\n\n%s\n.\n" % (from_addr, to_addr, subject, body)
return mailer.communicate(dialog)
And use it like:
send_mail ("Me <myself#mydomain.com>", "Recip Ient <other#hisdomain.com>", "Teh' Subject", "Mail body")
Either way, you need some backend (read MTA). Of the top of my head I can think of two things:
As already pointed out, you can for example use sendmail http://djangosnippets.org/snippets/1864/
Even better, use a Python MTA. There's Lamson, a Python email server (MTA): http://lamsonproject.org/docs/hooking_into_django.html

Categories