Send user authentication by mail - python

I am designing a program which the person (be user, admin, client, etc), register and this I sent an email with the authentication route and thus ends the registration process.
the person enters the page and places his email and password.
the app generates an access token and saves the email as identity, takes the email and sends the token with a link.
when clicking on the link redirects to the page, the app searches for the access token and thus allow the user to finish their registration process (name, surname, address, telephone, etc).
I am using python together with the flask framework. so far I have to do the access token and the authentication required to access the different routes. my problem is to send the link with the token to the person's email.
for sending mail I am using the SMTPLIB and this is the code
user = 'xxxxxxxxxx#gmail.com'
password = 'xxxxxxxxx'
remitente = 'xxxxxxxxxx#gmail.com'
destinatario = destinatario
asunto = 'Registro Exitoso'
mensaje = 'ok: nuevoenlace'
gmail = smtplib.SMTP('smtp.gmail.com', 587)
gmail.starttls()
gmail.login(user, password)
header = MIMEMultipart()
header['From'] = remitente
header['To'] = destinatario
header['Subject'] = asunto
mensaje = MIMEText(mensaje, 'html')
header.attach(mensaje)
gmail.sendmail(remitente, destinatario, header.as_string())
gmail.quit()
ok, my problem is to send the token by mail along with authentication link, this redirects me to a protected endpoint and finishes the entry process

If sending the email is the problem, here it says here you need to call
gmail.ehlo()
before calling gmail.starttls().
Find more information here: https://docs.python.org/3/library/smtplib.html
If this is not the problem, please provide more information or Stacktrace etc.

Related

does SMTP Authentication with an app password on Office 365 require a connector?

We recently enabled MFA on our account that sends out automated emails to staff/clients, so obviously we need a new way to authenticate that process. OAuth seems like overkill, so I went the "app password" route, which I've done seamlessly through services like Gmail.
But this just isn't working... I get the following error:
smtplib.SMTPAuthenticationError: (535, b'5.7.139 Authentication unsuccessful, the request did not meet the criteria to be authenticated successfully. Contact your administrator. [CH0PR03CA0182.namprd03.prod.outlook.com]')
Note that SMTP Authentication is turned on and I'm using STARTTLS 1.2. I've seen people pass parameters like:
SMTPSecure: 'tls'
SMTPAuth: true;
...but I don't know if that's needed for this, since it was working fine before the MFA switch. I also don't know where/how to send those with smtplib
Does anyone have any advice? I'm told I might need an SMTP Connector? Which also seems like an overcomplication of the process and wasn't mentioned in any MS article that instructed users on setting up app passwords. My code is below, fwiw. I haven't changed ANY of it since turning on MFA:
def send_mail(recipients: str, subject: str, body: str, attachments: list = None, cc: str = None):
credentials = get_credentials()
smtp_srv_name = "smtp.office365.com"
smtp_server = smtplib.SMTP(smtp_srv_name, 587)
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = 'xxxxxxxxxxxxx'
msg['To'] = recipients
msg['Cc'] = cc
msg.attach(MIMEText(body, 'plain'))
if attachments is not None:
for attachment in attachments:
with open(attachment, 'rb') as attachment_fileobject:
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment_fileobject.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', f"attachment; filename={Path(attachment).name}")
msg.attach(part)
smtp_server.starttls()
smtp_server.login('xxxxxxxxxxxxx', mc_decrypt(credentials['notices_email_pw'], CRYPT_KEY))
smtp_server.send_message(msg)
smtp_server.close()
Fixed it. All I had to do was disable Azure Security Defaults. The suggestion was in a MS support article that apparently isn't indexed on Google... so here's the content:
SMTP Authentication issues for Microsoft 365 Mailbox
If you are getting "Client not authenticated", "Authentication unsuccessful" OR "SmtpClientAuthentication" error with code 5.7.57 or 5.7.3 or 5.7.139 when trying to send email by authenticating a device or application with Microsoft 365, there are following three things you should perform to make it work:
Enable Client SMTP submission on the licensed mailbox being used-
Run the following Powershell command-
Set-CASMailbox -Identity sean#contoso.com -SmtpClientAuthenticationDisabled $false
Or
From Microsoft 365 Admin Center, go to Active Users and select the user
Go to Mail tab
In the “Email apps” section, click on “Manage email apps”
Verify the “Authenticated SMTP” setting is checked (enabled)
Click Save changes.
Disable the Azure Security Defaults by toggling the “Enable Security Defaults” to “No”.
Sign in to the Azure portal as a security administrator, Conditional Access administrator, or global administrator.
Browse to Azure Active Directory > Properties.
Select Manage security defaults.
Set the Enable security defaults toggle to No.
Select Save.
Disable Multi Factor Authentication (MFA) on the licensed mailbox being used -
In the Microsoft 365 Admin Center, in the left navigation menu choose Users > Active users.
On the Active users page, choose Multi-factor authentication.
On the multi-factor authentication page, select the user and disable the Multi-Factor auth status.

How can I send email from python with 2 Factor Authentication?

I have created python file that can send email using less secure apps turned on, but I need it off. How can I send email with 2FA?
# import simple mail transfer protocol library
import smtplib
# import EmailMessage method
from email.message import EmailMessage
contacts = ['<email#email.com>', '<email2#email.com>']
EMAIL_ADDRESS = '<my_gmail>'
EMAIL_PASSWORD = '<my_gmail_password>'
# Create empty Email Message object
msg = EmailMessage()
msg['Subject'] = 'Automated python email sender 5'
msg['From'] = EMAIL_ADDRESS
msg['To'] = contacts
msg.set_content('<sample_content>')
# contact manager we will make sure our connection is closed automatically without us doing it manually
# 465 is the port number for plain SMTP_SSL
# SMTP_SSL means you do not have to use ehlo() ans starttls()
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
smtp.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
smtp.send_message(msg)
What should I add to make 2FA work?
I believe you would need to set up an App passwords let you sign in to your Google Account from apps on devices that don't support 2-Step Verification. Learn more
Its basically something thats setup in the users Google account.
Another thing to look at would be Display captcha
if that doesn't work you might need to look into Xoauth2
if you require 2fa
If you want to support 2fa then you should not be using the SMTP server and should be going though the Gmail API and using Oauth2 which will prompt a user to connect via their google account and google will control the 2fa themselves. SMTP servers are not designed to handel 2fa
Try setting up App Password for your Gmail. and used that app password for smtp login.
This will help Set Up APP-Password
Under security you have to generate a password for your application:
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login('demo#gmail.com', 'password generated by google')
server.sendmail('demo#gmail.com', 'demo#icloud.com', 'Mail sent from program')
print('Mail Sent')
as you can see, you enter your email but instead of typing your own password you enter the password generated by google for your application

Gmail API Oauth2 Send from different address

I am able to send e-mails using Python and the google libraries (googleapiclient, google_auth_oauthlib.flow, and google.auth.transport.requests). I'm trying to get an alternate "from" or "reply-to" address, and it's not working. My code for creating a message is like so:
# Returns an e-mail message suitable for submission through the gmail api.
def create_message(sender, to, subject, message_text):
message = MIMEMultipart()
message['to'] = to
#message['from'] = sender
message['from'] = 'derp#nowhere.com'
message['subject'] = subject
message.attach(MIMEText(message_text, 'html'))
return {'raw': base64.urlsafe_b64encode(message.as_string().encode()).decode()}
As you can see, I've adjusted the from attribute of the message. When this message is sent, it is from the gmail account owner, not "derp". How do I make the message come from a different address?
Add the e-mail address as whom you want to issue e-mail as a "Send Mail As" account: https://mail.google.com/mail/u/2/#settings/accounts. It is necessary for that other account to verify he has control of that e-mail address.
It appears not to be possible to "spoof" e-mails using gmail oauth without this verification process, though if you use the deprecated "less secure apps", it is still possible.

sending emails with smtplib in python from shared mailbox

I am working on script to send emails.
Emails are supposed to be send from a shared mailbox in outlook.
This shared mailbox doesn't have a password and here is the trick: on the one hand I need the authenticate and provide a password, on the other hand I have no password to provide.
I ran the scripted with my professional outlook mailbox (email address + password) and it works.
Here is my config:
MY_ADDRESS = "---emailaddressofthesender---"
PASSWORD = ""
MESSAGE = "some message"
# set up the SMTP server
s = smtplib.SMTP(host='smtp-mail.outlook.com', port=587)
s.starttls()
s.login(MY_ADDRESS, PASSWORD)
msg = MIMEMultipart() # create a message
# setup the parameters of the message
msg['From']=MY_ADDRESS
msg['To']="---emailaddresseofthereceiver---"
msg['Subject']="This is TEST"
# add in the message body
msg.attach(MIMEText(MESSAGE, 'plain'))
# send the message via the server set up earlier.
s.send_message(msg)
del msg
# Terminate the SMTP session and close the connection
s.quit()
I tried:
Read the doc smtplib. Unless mistaken, I found no mentions about
authentications without password.
PASSWORD = "": authentication error
PASSWORD = None: authentication error
s.login(MY_ADDRESS): PASSWORD argument is missing
remove s.login() method from the script: Client was not authenticated to send anonymous mail during MAIL FROM [PR0P264CA0184.FRAP264.PROD.OUTLOOK.COM]
The only working solution I have now is to send from my mailbox credentials and not from the shared mailbox. For the sake of this project, this solution is not acceptable.
Many thanks in advance for your help
Add this right before the s.send() step and it will work.
s.SentOnBehalfOfName = 'SharedFolder'

Emails which are sent by python script drop in Spam on GMail

After registration on our service user is sent by email with confirmation link.
But when it is sent to Gmail or other mail services it usually drops to spam.
Here is the code:
def email_user(self, subject, message, from_email=None):
send_mail(subject, message, from_email, [self.email])
def activate_email(self, email=None):
if email: self.email = email
self.is_activated = False
self.activation_code = hashlib.sha256(str(self.email) + os.urandom(256)).hexdigest()[:32]
self.save()
subject = u'Welcome to the {0}!'.format(settings.SITE_NAME)
message = render_to_string('users/emails/activation.html', {'activation_code': self.activation_code, 'site_name': settings.SITE_NAME, 'site_domain': settings.SITE_DOMAIN})
self.email_user(subject, message, settings.SITE_EMAIL)
How to add DKIM or other license to this email in order to make Google trust to our server?
We're using Zimbra mail server on our site domain.
P.S. I found this snippet: https://djangosnippets.org/snippets/1995/
Is it suitable somehow in my case or not?
Thank you!
How your mail is treated depends first and foremost on the configuration of the email server which sends the messages generated by your application, and the DNS records associated with it.
Google's guidelines for bulk senders are a great place to start. Check that your mail server (and the emails themselves) comply with the rules.
DKIM is one of these guidelines, so yes: adding DKIM signatures will help. A few other points in the guide:
"Use the same address in the 'From:' header on every bulk mail you send." If you used different From headers while testing or something, this could be the problem.
Publish an SPF record.
Publish a DMARC policy.

Categories

Resources