I want to mark the gmail messages Seen by imaplib - python

I want to parse some gmail emails by python.
I want when the message is read to put it seen.
I put this code but it is not marked as seen?
#read or seen email
mail.store(i,'+FLAGS', '\\Seen')
Do you know how I can keep the email looking whether it is VIEWED?
mport imaplib,dateutil.parser
import email
###################### mail read code ###################
mail=imaplib.IMAP4_SSL('imap.gmail.com',993) #SMTPは993,POPは995
mail.login('example#co.jp','12123')
mail.select('example.jp',readonly=True) #mailbox select read only
#UNSEEN read mail
type,data=mail.search(None,'UNSEEN')
for i in data[0].split(): #data loop
ok,x=mail.fetch(i,'RFC822') #mail information get
ms=email.message_from_string(x[0][1].decode('iso-2022-jp')) #pass get
#from get
ad=email.header.decode_header(ms.get('From'))
ms_code=ad[0][1]
if(ms_code!=None):
address=ad[0][0].decode(ms_code)
address+=ad[1][0].decode(ms_code)
else:
address=ad[0][0]
#Title get
sb=email.header.decode_header(ms.get('Subject'))
ms_code=sb[0][1]
if(ms_code!=None):
sbject=sb[0][0].decode(ms_code)
else:
ms_code=sb[1][1]
sbject=sb[1][0].decode(ms_code)
#body get
maintext=ms.get_payload()
#read email
mail.store(i,'+FLAGS', '\\Seen')
print(sbject)
print(address)
print(maintext)

I guess you may want to have a read of Gmail API reference on labels but very likely you are in need to remove labels UNREAD from the e-mail you want to be marked as read. For that you would have to use REST API or googleapiclient Python library.

If you open your mailbox read-only, you can't make changes to it, including storing flags:
mail.select('example.jp',readonly=True) #mailbox
Remove the read-only flag.

Related

Transfer an email with Python

I've tried with no conclusions to resend emails with Python.
Once I've logged in SMTP and IMAP with TLS, this is what I have written:
status, data = self._imapserver.fetch(id, "(RFC822)")
email_data = data[0][1]
# create a Message instance from the email data
message = email.message_from_string(email_data)
# replace headers (could do other processing here)
message.replace_header("From", 'blablabla#bliblibli.com')
message.replace_header("To", 'blobloblo#blublublu.com')
self._smtpserver.sendmail('blablabla#bliblibli.com', 'blobloblo#blublublu.com', message.as_string())
But the problem is that the variable data doesn't catch the information from the email, even if the ID is the one I need.
It tells me:
b'The specified message set is invalid.'
How can I transfer an email with Python?
Like the error message says, whatever you have in id is invalid. We don't know what you put there, so all we can tell you is what's already in the error message.
(Also, probably don't use id as a variable name, as you will shadow the built-in function with the same name.)
There are additional bugs further on in your code; you need to use message_from_bytes if you want to parse it, though there is really no need to replace the headers just to resend it.
status, data = self._imapserver.fetch(correct_id, "(RFC822)")
self._smtpserver.sendmail('blablabla#bliblibli.com', 'blobloblo#blublublu.com', data[0][1])
If you want to parse the message, you should perhaps add a policy argument; this selects the modern EmailMessage API which was introduced in Python 3.6.
from email.policy import default
...
message = email.message_from_bytes(data[0][1], policy=default)
message["From"] = "blablabla#bliblibli.com"
message["To"] = "blobloblo#blublublu.com"
self._smtpserver.send_message(message)
The send_message method is an addition to the new API. If the message could contain other recipient headers like Cc:, Bcc: etc, perhaps using the good old sendmail method would be better, as it ignores the message's headers entirely.

How to send a draft email that I've prepared in several to several contacts in gmail one by one?

I have prepared a draft email in Gmail that I need to send to several people but Gmail does not allow me to. The draft email has text, an image in it, and formatting.
I'd ideally want to send the draft to my list of contacts one by one just changing who it's addressed to. I can put the list of contacts in one column of excel and the name in another.
I could also just make the draft start with "Dear sir/madam" and send the same draft to my contacts without any modification.
If the body of my email was just text I guess I'd just use SMTP, but with all the formatting, and image in it I don't know what to do.
What is the easiest way to do this? Would using Selenium make sense? Anything else that's better?
Thanks
You could use a JavaMail API to send email.
For formatting you can use the html formatting inside your code, which serves like your draft.
Read the contacts from a file and replace the variable in "Dear" $varName.
And to trigger it multiple times you could use java.util.Timer class.
Hope it helps.
Here's what worked for me to send an email using python. I turned my email content into html and saved in a file and named it emailcontent. Then I used it in the following code:
import smtplib
from email.message import EmailMessage
from emailcontent import emailcontent
from config import email, password
email_list = ["user#gmail.com", "user2#yahoo.ca",
"user3#gmx.us", "user4#u.ca"]
for useremail in email_list:
msg = EmailMessage()
msg['Subject'] = 'Test'
msg['From'] = email
msg['To'] = useremail
msg.set_content('fallback')
msg.add_alternative(emailcontent, subtype='html')
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as smtp:
smtp.login(email, password)
smtp.send_message(msg)

Python win32com: set email header

I have an issue to write in an email header in python using library win32com.
But I'm not sure if it is possible.
We can read an email header using:
import win32com.client
outlook =win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox=outlook.GetDefaultFolder(6)
messages = inbox.Items
message = messages.GetLast()
mess=message.Body
internet_header = message.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001F")
print(internet_header)
But I don't know if we can set the email header using something similar.
it is not working using something like that:
new_mail.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001F", internet_header)
Any idea?
Thanks
To set a MIME header on an outgoing email, set a named property in the PS_INTERNET_HEADERS namespace:
message.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/string/{00020386-0000-0000-C000-000000000046}/X-My-Header", "some value")

Using Python and gmail API, how can I send messages with multiple attachements?

Looking to create and send messages with multiple files attached. Per the online gmail api documentation, there is a function for building messages with an attachment but no documentation for howto use it to create a message with multiple attachments.
Can I use the gmail API to send messages with multiple attachments programmatically? How might one do this?
With this function, you can send to one or multiple recipient emails, and also you can attach zero, one or more files. Coding improvement recommendations are welcome, however the way it is now, it works.
Python v3.7
smtplib from https://github.com/python/cpython/blob/3.7/Lib/smtplib.py (download the code and create the smtplib.py on your project folder)
def send_email(se_from, se_pwd, se_to, se_subject, se_plain_text='', se_html_text='', se_attachments=[]):
""" Send an email with the specifications in parameters
The following youtube channel helped me a lot to build this function:
https://www.youtube.com/watch?v=JRCJ6RtE3xU
How to Send Emails Using Python - Plain Text, Adding Attachments, HTML Emails, and More
Corey Schafer youtube channel
Input:
se_from : email address that will send the email
se_pwd : password for authentication (uses SMTP.SSL for authentication)
se_to : destination email. For various emails, use ['email1#example.com', 'email2#example.com']
se_subject : email subject line
se_plain_text : body text in plain format, in case html is not supported
se_html_text : body text in html format
se_attachments : list of attachments. For various attachments, use ['path1\file1.ext1', 'path2\file2.ext2', 'path3\file3.ext3']. Follow your OS guidelines for directory paths. Empty list ([]) if no attachments
Returns
-------
se_error_code : returns True if email was successful (still need to incorporate exception handling routines)
"""
import smtplib
from email.message import EmailMessage
# Join email parts following smtp structure
msg = EmailMessage()
msg['From'] = se_from
msg['To'] = se_to
msg['Subject'] = se_subject
msg.set_content(se_plain_text)
# Adds the html text only if there is one
if se_html_text != '':
msg.add_alternative("""{}""".format(se_html_text), subtype='html')
# Checks if there are files to be sent in the email
if len(se_attachments) > 0:
# Goes through every file in files list
for file in se_attachments:
with open(file, 'rb') as f:
file_data = f.read()
file_name = f.name
# Attaches the file to the message. Leaves google to detect the application to open it
msg.add_attachment(file_data, maintype='application', subtype='octet-stream', filename=file_name)
# Sends the email that has been built
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
smtp.login(se_from, se_pwd)
smtp.send_message(msg)
return True
Don't forget to activate less secure apps on your google account (https://myaccount.google.com/lesssecureapps) for this code to work.
Hope this helps

how to sign request tokens?

I am currently trying to write a script to send off a request token, I have the header, and the claimset, but I don't understand the signature! OAuth requires my private key to be encrypted with SHA256withRSA (also known as RSASSA-PKCS1-V1_5-SIGN with the SHA-256 hash function), but the closest I could find was RSAES-PKCS1-v1_5 (has RSA, and the SHA-256 hash). I followed the example, and tweaked it, so I could get it set, but heres my dillema:
signature = ""
h = SHA.new (signature)
key = RSA.importKey(open('C:\Users\Documents\Library\KEY\My Project 905320c6324f.json').read())
cipher = PKCS1_v1_5.new(key)
ciphertext = cipher.encrypt(message+h.digest())
print(ciphertext)
I'm a bit lost, the JSON file I was given has both public key, and private, do I copy and paste the private key into the signature variable (it gave me a invalid syntax)? Or do I past the directory again? I am so lost, and way over my head haha. I am currently running Python 3.4, with pyCrypto for the signature.
Based on what you've said below about wanting to write a command system using gmail, I wrote a simple script to do this using IMAP. I think this is probably simpler than trying to use Google APIs for a single user, unless you were wanting to do that simply for the exercise.
import imaplib, logging
from time import sleep
USERNAME = 'YOUR_USERNAME_HERE' # For gmail, this is your full email address.
PASSWORD = 'YOUR_PASSWORD_HERE'
CHECK_DELAY = 60 # In seconds
LOGGING_FORMAT = '%(asctime)s %(message)s'
logging.basicConfig(filename='imapTest.log', format=LOGGING_FORMAT, level=logging.INFO)
logging.info("Connecting to IMAP server...")
imap = imaplib.IMAP4_SSL('imap.gmail.com')
imap.login(USERNAME, PASSWORD)
logging.info("Connected to IMAP server.")
def get_command_messages():
logging.info("Checking for new commands.")
imap.check()
# Search the inbox (server-side) for messages containing the subject 'COMMAND' and which are from you.
# Substitute USERNAME below for the sending email address if it differs.
typ, data = imap.search(None, '(FROM "%s" SUBJECT "COMMAND")' %(USERNAME))
return data[0]
def delete_messages(message_nums):
logging.info("Deleting old commands.")
for message in message_nums.split():
imap.store(message, '+FLAGS', '\\DELETED')
imap.expunge()
# Select the inbox
imap.select()
# Delete any messages left over that match commands, so we are starting 'clean'.
# This probably isn't the nicest way to do this, but saves checking the DATE header.
message_nums = get_command_messages()
delete_messages(message_nums)
try:
while True:
sleep(CHECK_DELAY)
# Get the message body and sent time. Use BODY.PEEK instead of BODY if you don't want to mark the message as read, but we're deleting it anyway below.
message_nums = get_command_messages()
if message_nums:
# search returns space-separated message IDs, but we need them comma-separated for fetch.
typ, messages = imap.fetch(message_nums.replace(' ', ','), '(BODY[TEXT])')
logging.info("Found %d commands" %(len(messages[0])))
for message in messages[0]:
# You now have the message body in the message variable.
# From here, you can check against it to perform commands, e.g:
if 'shutdown' in message:
print("I got a shutdown command!")
# Do stuff
delete_messages(message_nums)
finally:
try:
imap.close()
except:
pass
imap.logout()
If you're set on using the Gmail API, though, Google strongly encourage you to use their existing Python library rather than attempt to do full authentication etc. yourself as you appear to be. With that, it should - more or less - be a case of replacing the imap calls above with the relevant Gmail API ones.

Categories