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

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.

Related

SMTPAuthenticationError while sending mail using Python

when I try to send mail using outlook and python error occurred this type of question is already on this site but doesn't help to me.
from redmail import outlook
outlook.user_name = "example#hotmail.com"
outlook.password = "<MY PASSWORD>"
outlook.send(
receivers=["you#example.com"],
subject="An example",
text="Hi, this is an example."
)
Error logs:
SMTPAuthenticationError: (535, b'5.7.139 Authentication unsuccessful, basic authentication is disabled. [MA0PR01CA0094.INDPRD01.PROD.OUTLOOK.COM]')
This may be related to the security vulnerability of OpenSSL.https://www.openssl.org/source/
It seems that Microsoft has restricted the 25 port of SMTP service.
But this problem was solved last night. Now I can normally access both Python and Java.

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.

IMAP with python to download attachments

I have a instrument at work that emails me a file containing raw data, I can go into my email and download them easily enough but when I have multiple files (which it sends as multiple emails) it gets a bit tedious.
I'm looking at using python and imaplib to login to my email account, search for emails from a known email address within the past day or so and then download any attachments to a directory. So I thought a script might help here.
I've setup a gmail account and altered the settings so that I can connect using imap from a shell, however I'm lost as to where to go from here.
Could someone point me in the right direction as to what I need to do to make this happen.
Here is a repository that is forked off imaplib (made compatible with Python3.6, did not test other versions)
https://github.com/christianwengert/mail
The following snippet checks all unseen messages, then returns their attachments:
server = IMAPClient(imap, use_uid=True, ssl=993)
server.login(username, password)
server.select_folder('INBOX')
message_ids = server.search([b'NOT', b'SEEN']) # UNSEEN
messages = server.fetch(message_ids, data=['ENVELOPE', 'BODYSTRUCTURE', 'RFC822.SIZE'])
for mid, content in messages.items():
bodystructure = content[b'BODYSTRUCTURE']
text, attachments = walk_parts(bodystructure, msgid=mid, server=server)
HTH

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)

Categories