I'm sure this has been asked, but I can't find anything to get mine to work.
I'm trying to send follow up emails to clients, but I want to spoof the email address so the from address is for my coworker. I read somewhere online that the from address in the header is simply a text field that can be edited, but I still cannot send the email.
import smtplib
email_to = '*****#gmail.com'
username = '*******#outlook.com'
password = '*********'
other_email = '*******#outlook.com'
mail = smtplib.SMTP('Outlook.com', 25)
mail.ehlo()
mail.starttls()
mail.login(username,password)
header = ('To:' + email_to + '\n' +'From: ' + other_email + '\n'
+ 'Subject: Python Project Test\n')
message = (header +
'\n\n This is a test message generated from a Python script. \n\n')
mail.sendmail(username, email_to, message)
mail.close()
print("Email sent successfully.")
I know this can be done, but can someone point me in the right direction? Is there any way for me to disguise my name in the from field as that of the email that is supposed to get this?
===================================
Also, for the sake of completion, here is the error I got:
Traceback (most recent call last):
File "C:\Users\*****\Desktop\email outlook.py", line 16, in <module>
mail.sendmail(username, email_to, message)
File "C:\Users\*****\AppData\Local\Programs\Python\Python36-32\lib\smtplib.py", line 887, in sendmail
raise SMTPDataError(code, resp)
smtplib.SMTPDataError: (550, b'5.7.60 SMTP; Client does not have permissions to send as this sender')
I was hoping if there was a way to make the other_name an alias of the username.
The very short version: This isn't going to work.
Once upon a time, it was reasonably possible to do what you are asking to do. In the old days, when the internet was small and spam did not exist, the receiving server would just trust you. You could just connect to mail.example.com and say you were sending on behalf of someone#example.org, and example.com would just believe you.
But those days are over and done with. Nowadays, SMTP servers are a lot less trusting. So let's go through the problems with your approach:
You are trying to route your email through outlook.com. outlook.com knows perfectly well that you are username and not other_email. If you want to send email as other_email, you need to authenticate as other_email.
You could connect directly to gmail.com, claim to be outlook.com, and try to send the email that way. But Gmail knows you're not outlook.com, because you're missing these things. So it will likely flag your message as spam, bounce it, or even* accept it and then discard it entirely.
You could fix (1) by changing your code, but because of (2), there's little point.
* I do not work on the Gmail team. I am guessing how Gmail would respond to this based solely on public information about how modern email servers are typically configured. YMMV.
Related
I am trying to build a email chatbot but it has this bug where after it sends the first message, and then gets a response it keeps spamming the answered to the response it got until it gets another response which then it repeats again I was thinking to solve this I should use a variable which detects emails and later down the code a condition that responds only if a email is received, does anyone have any idea on how I could fix this? Thanks
def receive_email():
try:
mail = imaplib.IMAP4_SSL("smtp.gmail.com")
mail.login(email_address, email_password)
mail.select('inbox')
#searches inbox
status, data = mail.search(None, 'Recent')
mail_ids = data[0].split()
latest_email_id = mail_ids[-1]
status, data = mail.fetch(latest_email_id, '(RFC822)')
#gets message
for response_part in data:
if isinstance(response_part, tuple):
msg = email.message_from_bytes(response_part[1])
sender = msg['from']
subject = msg['subject']
if msg.is_multipart():
for part in msg.get_payload():
if part.get_content_type() == 'text/plain':
return part.get_payload()
message = msg.get_payload()
return message,
except Exception as e:
print("Error: ", e)
print("Could not receive email")
return None, None
This is the usual problem for an email autoresponder, if I understand you correctly, and RFC 3834 offers good advice.
Since answers should be self-contained I offer a summary:
Add the Auto-Submitted: auto-replied header field on your outgoing messages. Any value other than no will prevent well-written autoresponders from replying to your outgoing messages.
Set the \answered flag on the message you reply to, immediately before you send the reply.
Change the search key from recent to unanswered not header "auto-submitted" "". unanswered means that the search won't match the messages on which you set the \answered flag, not header "auto-submitted" "" means that you'll not match messages that contain any auto-submitted header field.
Direct your replies to the address in return-path or sender, not the one in from. This is a matter of convention. Auto-submitted mail will often have a special return-path that points to an address that never sends any autoreply.
You may also extend the search key with more details from RFC 3834. The one I suggest should work, but not header "precedence" "junk" will for example prevent your code from replying to a bit of autogenerated mail. Sendgrid and its friends also add header fields you may want to look for and exclude.
If the incoming message has headers like this (use the "view headers" function of most mail readers to see it):
From: example#example.com
Subject: Weekend
To: srtai22#gmail.com
Message-id: <56451182ae7a62978cd6f6ff06dd21e0#example.com>
Then your reply should have headers like this:
Return-Path: <>
From: srtai22#gmail.com
To: example#example.com
Auto-Submitted: auto-replied
Subject: Auto: Weekend
References: <56451182ae7a62978cd6f6ff06dd21e0#example.com>
There'll be many more fields in both, of course. Your reply's return-path says that nothing should respond automatically, From and To are as expected, auto-submitted specifies what sort of response this is, subject doesn't matter very much but this one's polite and well-behaved, and finally references links to the original message.
I am trying to use Sendgrid to send the email on Heroku, but I get the output that I not seen before. I saw the documentation and it says that the helper library supports few versions of python until 3.8 but mine version is 3.9. Is it this cause me get this error?
**Here is my code: **
import os
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
message = Mail(
from_email='hesheitaliabu#gmail.com',
to_emails='hesheitaliabu#gmail.com',
subject='Sending with Twilio SendGrid is Fun',
html_content='<strong>and easy to do anywhere, even with Python</strong>')
try:
sg = SendGridAPIClient('SG.API_KEY')
response = sg.send(message)
# print(response.status_code)
print(response.body)
print(response.headers)
except Exception as e:
print(e.message)
I get an error:
b''
Server: nginx
Date: Mon, 05 Sep 2022 03:53:19 GMT
Content-Length: 0
Connection: close
X-Message-Id: Y19VjElqRe2byQxJrkJUeg
Access-Control-Allow-Origin: https://sendgrid.api-docs.io
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Authorization, Content-Type, On-behalf-of, x-sg-elas-acl
Access-Control-Max-Age: 600
X-No-CORS-Reason: https://sendgrid.com/docs/Classroom/Basics/API/cors.html
Strict-Transport-Security: max-age=600; includeSubDomains
As we've worked out in the comments, the emails are in fact sending successfully. The message you see logged are the response headers from the API because of these lines:
sg = SendGridAPIClient('SG.API_KEY')
response = sg.send(message)
print(response.body)
print(response.headers)
In this case the message is sent and then the program prints out the response body (which is empty for a successfully sent message) and then the response headers, which you are seeing. This is not an error.
Instead, we have worked out that your email is being sent to the spam inbox.
This is a bit harder to fix as it relies on email inbox providers. However I need to point out one thing that's going to make this very difficult to start with.
Your example shows that you are sending the email from your Gmail address to the same Gmail address. Because of this, Gmail knows it did not send the email from that Gmail address and will instantly treat it as suspicious. You are effectively spoofing your own email address. If you have set up single sender verification with SendGrid for that address, all that does is tell SendGrid that you own the email address and aren't trying to spoof just anyone's email address. This is good for testing that you can use the API to send emails.
However, if you want emails to arrive in inboxes and not the spam inbox then your best bet is to send from a domain that you own that you can authenticate with SendGrid. When you authenticate a domain it sets a number of things like SPF and DKIM that show the inboxes you are sending to that you are the rightful owner of the domain and are authenticated to send emails from the domain. This means you are more likely to arrive in the inbox and not spam.
There is much more to pay attention to to ensure your emails stay out of spam, but in this case, I would start with domain authentication.
I used the code below to try to send an email to my teacher with my email and password:
import cs50
import smtplib
from email.message import EmailMessage
def main():
message = EmailMessage()
message.set_content("This email verifies run-check of ASSIGNMENT")
message['Subject'] = 'Assignment from ME'
message['From:'] = 'MY EMAIL'
message['To:'] = 'TEACHER'S EMAIL'
with smtplib.SMTP_SSL('smtp.gmail.com') as smtp:
smtp.login("MY EMAIL", "MY PASSWORD")
smtp.send_message(message)
sys.exit(0)
if(__name__ == "__main__"):
main()
However, I got an error message saying "TypeError: sequence item 0: expected str instance, NoneType found". Any idea what went wrong? It just took me 30 minutes of trying to get the login to work with Less Secure Apps...
Edit: No, the problem is not the third apostrophe in 'TEACHER'S EMAIL'. in the actual teacher's email there is not apostrophe yet I still get the TypeError problem.
Edit 2: Whole error code here:
Traceback (most recent call last):
File "/home/ubuntu/some folder idk/SMF29.py", line 48, in <module>
main()
File "/home/ubuntu/some folder idk/SMF29.py", line 42, in main
smtp.send_message(message)
File "/usr/local/lib/python3.9/smtplib.py", line 940, in send_message
from_addr = email.utils.getaddresses([from_addr])[0][1]
File "/usr/local/lib/python3.9/email/utils.py", line 112, in getaddresses
all = COMMASPACE.join(fieldvalues)
TypeError: sequence item 0: expected str instance, NoneType found
Edit 3: seeing that some people surrounded their emails with <>, I tried that, and got a different error:
smtplib.SMTPAuthenticationError: (535, b'5.7.8 Username and Password not accepted. Learn more at\n5.7.8 https://support.google.com/mail/?p=BadCredentials l11sm1375218qkk.101 - gsmtp')
Which is confusing, because not only have I taken all the google steps including the enable less secure apps and verify device things, but I am only logged into that one account. Any idea what the problem could be?
Edit 4: turns out that was a stupid idea and after getting rid of the <>s around the emails and the colons in front of From and To it worked. I had previously accidentally forgotten to remove one pair of <> around my email after removing the colons.
As can be seen from the error traceback, specifically this line:
from_addr = email.utils.getaddresses([from_addr])[0][1]
You are missing the from_addr. The key for the From address is From, not From: (with a colon). Change the following line
message['From:'] = 'MY EMAIL'
to
message['From'] = 'MY EMAIL'
While you are at it, do the same for the To address as well.
See the docs for an example.
I am trying to send a simple mail with python
import smtplib
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.login("mymail#gmail.com", "mypassword")
msg = "Hello world"
server.sendmail("mymail#gmail.com", "mymail#gmail.com", msg)
server.quit()
But I get this err:
server.login("user#gmail.com", "psw")
File "C:\Python\lib\smtplib.py", line 652, in login
raise SMTPAuthenticationError(code, resp)
smtplib.SMTPAuthenticationError: (534, b'5.7.14 <https://accounts.google.com/ContinueSignIn?sarp=1&scc=1&plt=AKgnsbuxb\n5.7.14 4i2u8qU8V3jgf6uGv8da1RAGPJyctRvIFy_kjai6aKVx_B6qVhoz_dzFpvfPC18H-jeM6K\n5.7.14 cnm2HVuq-wr-uw59hD31ms-cxMmnZuq6Z3_liDaDmu8_UqaiUwR4FUiuX2i5pPdQjJzFvv\n5.7.14 4VrEF5XT4ol2iN17gnB_jITpwzsjH9Ox3NCNcfl7SriHr5m7esc15PWI0CG_2CTlyh7RxW\n5.7.14 XhoJPajs8GMd-khOQWUqucywfrfo> Please log in via your web browser and\n5.7.14 then try again.\n5.7.14 Learn more at\n5.7.14 https://support.google.com/mail/bin/answer.py?answer=78754 ef10sm13614207wjd.49 - gsmtp')
What should I do?
Thanks
It seems as if you require something that Google calls an app password.
Basically, you generate a 16 digit password, which is unique to your app. You enter this specific password in the python program, instead of the password you regularly use to log into your Google account.
This allows you to still enjoy the benefits of 2-step verification while also being able to use third party applications, such as your own python program.
Here are the instructions from Google on how to generate such an app password:
https://support.google.com/accounts/answer/185833?hl=en
you can use this code:
import smtplib
session = smtplib.SMTP('smtp.gmail.com', 587)
session.ehlo()
session.starttls()
session.login('youremail#gmail.com',' password')
headers = "\r\n".join(["from: " + 'youremail#gmail.com',
"subject: " + "test",
"to: " + 'contactemail#gmail.com',
"mime-version: 1.0",
"content-type: text/html"])
# body_of_email can be plaintext or html!
content = headers + "\r\n\r\n" + "body_of_email"
session.sendmail('youremail#gmail.com', 'contactemail#gmail.com', content)
just remember if your email is gmail after first run you get an error. after that you should login to your email account and approve access to your account from another app ( you will receive a messege after login)
You could use a free mail API such as mailgun:
import requests
def send_simple_message(target):
return requests.post(
"https://api.mailgun.net/v3/samples.mailgun.org/messages",
auth=("api", "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"),
data={"from": "Excited User <excited#samples.mailgun.org>",
"to": [target],
"subject": "Hello",
"text": "Testing some Mailgun awesomeness!"})
send_simple_message('target#email.com')
Using an API like this avoids the issue of individual account authentication all together.
See also: This question for info on using smtplib
Yea, like the answer posted, it was a matter of authentication :)
I'd like to further help you with sending emails by advising the yagmail package (I'm the maintainer, sorry for the advertising, but I feel it can really help!). Note that I'm also maintaining a list of common errors there, such as the authentication error.
The whole code for you would be:
import yagmail
yag = yagmail.SMTP('user', 'pw')
yag.send(contents = msg)
Note that I provide defaults for all arguments, for example if you want to send to yourself, you can omit "to = myemail#gmail.com", if you don't want a subject, you can omit it also.
Furthermore, the goal is also to make it really easy to attach html code or images (and other files).
Where you put contents you can do something like:
contents = ['Body text, and here is an embedded image:', 'http://somedomain/image.png',
'You can also find an audio file attached.', '/local/path/song.mp3']
Wow, how easy it is to send attachments! This would take like 20 lines without yagmail ;)
Also, if you set it up once, you'll never have to enter the password again (and have it safely stored). In your case you can do something like:
import yagmail
yagmail.SMTP().send(contents = contents)
which is much more concise!
I'd invite you to have a look at the github or install it directly with pip install yagmail.
I am writing a Python program that can login Gmail.
The purpose of this program is to check whether the username/password combination exists and is correct.
Since this program is to test the the username/password combination existence, it's no need to know any mail contents in Gmail.
The input of this program is a username and password.
The output of this program is either
successful login
or
login failure
Login failure could be:
existing username+wrong password
nonexisting username
My idea is to login Gmail first. Afterward, when login failure, the gmail webpage will show particular message on the login webpage. I can parse the webpage content and check whether it has that particular message.
However, I still have no idea how to login Gmail in Python. Please let me know which module can be used or write me a small piece of sample code.
Here's an idea:
Why don't you try to send an email from the account and see if it sends? You can do this with smtplib in the python standard module. There's code examples here. You'll have to look into the doc of the module, but it looks like an exception is thrown if the login fails, which should contain the details you're interested in.
In edit:
I dug up this bit of code that I wrote to do exactly that. You'll need to put a try/catch around the bit at the bottom to detect erroneous login credentials.
# Subject
now = dt.datetime.now().ctime()
subject = 'Change to system on %s' % now
# Body
body = 'Subject: %s,\n' % subject
body += 'On %s, a change to the system was detected. Details follow.\n\n' % now
relevantFiles = list(set([x.file for x in relevantChunks]))
for file in relevantFiles:
fileChunks = [x for x in relevantChunks if x.file == file]
for chunk in fileChunks:
body += '****** Affected file %s. ' % chunk.file
<some other stuff>
server = smtp.SMTP(args.host) # host = smtp.gmail.com:<port> look this bit up
server.starttls()
server.login(args.username, args.password)
server.sendmail(args.sender, args.recipient, body)
server.quit()
As an aside, I'm not quite sure why this question was down-voted, or even what it takes to be down-voted other than the fact that you asked the wrong question.
try this:
from email.mime.text import MIMEText
import smtplib
msg = MIMEText("Hello There!")
msg['Subject'] = 'A Test Message'
msg['From'] = 'username#gmail.com'
msg['To'] = 'username#gmail.com'
s = smtplib.SMTP('smtp.gmail.com:587')
s.starttls() ##Must start TLS session to port 587 on the gmail server
s.login('username', 'passsword') ##Must pass args gmail username & password in quotes to authenticate on gmail
s.sendmail('username#gmail.com',['username#gmail.com'],msg.as_string())
print("Message Sent")
This kind of things are like prohibited, that's why things like OAuth or OpenID are created. This kind of things permit the user to login without entering username and password. So be careful.