How would I ago about coding a Python script to work whenever there is a new email in my inbox. Is there any special tools in the Gmail Python SDK that would make this easy to do instead of using MAPI and going the long rout of keep checking daily for new inbox updates?
You can use something like this.
def get_email():
#credentials
username ="youremail#gmail.com"
#generated app password
app_password= "emailPasswd"
# https://www.systoolsgroup.com/imap/
gmail_host= 'imap.gmail.com'
#set connection
mail = imaplib.IMAP4_SSL(gmail_host)
#login
mail.login(username, app_password)
#select inbox
mail.select("INBOX")
time.sleep(1)
#select specific mails
_, selected_mails = mail.search(None,"UNSEEN", '(FROM "specificUser#gmail.com")') # get emails only from specific sender
#total number of mails from specific user
for num in selected_mails[0].split():
your_function() # call your function here so for every new mail this will run
_, data = mail.fetch(num , '(RFC822)')
_, bytes_data = data[0]
#access data
subject_of_mail = email_message["subject"]
for part in email_message.walk():
if part.get_content_type()=="text/plain" or part.get_content_type()=="text/html":
message = part.get_payload(decode=True)
else:
pass
schedule.every(5).seconds.do(get_email)
#other schedule options
"""
schedule.every(10).minutes.do(get_email)
schedule.every().hour.do(get_email)
schedule.every().day.at("10:30").do(get_email)
schedule.every(5).to(10).minutes.do(get_email)
schedule.every().monday.do(get_email)
schedule.every().wednesday.at("13:15").do(get_email)
schedule.every().minute.at(":17").do(get_email)
"""
while True:
schedule.run_pending()
time.sleep(1)
Related
I wanna get a message when a new email into outlook.
I try to use python.
I can find that folders,but can't find the way to get the number of new email.
import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
accounts = win32com.client.Dispatch("Outlook.Application").Session.Accounts;
inbox = outlook.Folders(accounts[0].DeliveryStore.DisplayName)
for obj in inbox.Folders: #how to know how many new email in this dir?
try:
if hasattr(obj, "__str__"):
dirName = obj.__str__() #as some new email in this obj.
for message in obj.items: # how to know this email is not be read ?
subject = sender = ''
if hasattr(message, "Subject"):
subject = message.Subject
if hasattr(message, "SenderName"):
sender = message.SenderName
print(sender, subject)
except Exception as e:
print(f"i:{obj.__str__()}")
and where can I learn win32com.mapi?
I wanna know what func can I use in mapi.
give me some info,please~
so much thanks!
Are you looking for unread messages? Use MAPIFolder.Items.Restrict("[Unread] = true") to retrieve Items collection with the restriction applied.
iam trying to use a imap with python but iam getting error every time, i followed all steps to active imap from gmail and unlock captcha but after the firt run iam getting this error pls help already thanks
raise self.error(dat[-1])
imaplib.error: b'[AUTHENTICATIONFAILED] Invalid credentials (Failure)'
after the gmail i got a Alerte security from gmail and all acces from imap is blocked
the code used `
# Importing libraries
import imaplib, email
user = 'USER_EMAIL_ADDRESS'
password = 'USER_PASSWORD'
imap_url = 'imap.gmail.com'
# Function to get email content part i.e its body part
def get_body(msg):
if msg.is_multipart():
return get_body(msg.get_payload(0))
else:
return msg.get_payload(None, True)
# Function to search for a key value pair
def search(key, value, con):
result, data = con.search(None, key, '"{}"'.format(value))
return data
# Function to get the list of emails under this label
def get_emails(result_bytes):
msgs = [] # all the email data are pushed inside an array
for num in result_bytes[0].split():
typ, data = con.fetch(num, '(RFC822)')
msgs.append(data)
return msgs
# this is done to make SSL connnection with GMAIL
con = imaplib.IMAP4_SSL(imap_url)
# logging the user in
con.login(user, password)
# calling function to check for email under this label
con.select('Inbox')
# fetching emails from this user "tu**h*****1#gmail.com"
msgs = get_emails(search('FROM', 'MY_ANOTHER_GMAIL_ADDRESS', con))
# Uncomment this to see what actually comes as data
# print(msgs)
# Finding the required content from our msgs
# User can make custom changes in this part to
# fetch the required content he / she needs
# printing them by the order they are displayed in your gmail
for msg in msgs[::-1]:
for sent in msg:
if type(sent) is tuple:
# encoding set as utf-8
content = str(sent[1], 'utf-8')
data = str(content)
# Handling errors related to unicodenecode
try:
indexstart = data.find("ltr")
data2 = data[indexstart + 5: len(data)]
indexend = data2.find("</div>")
# printtng the required content which we need
# to extract from our email i.e our body
print(data2[0: indexend])
except UnicodeEncodeError as e:
pass
'
If you are running this on a cloud host or the like, this will likely never work without implementing OAuth authentication (or maybe app specific passwords).
Google's account security appears to be set up to only allow logins from likely end-user hosts. If you're running it on your personal machine (that you also log in from), you will have to activate the reduced security setting, generate an app specific password, or implement OAuth.
I would like to save an email to the drafts folder of a shared mailbox using the win32 API for Outlook. I can save an email to my (default?) mailbox drafts folder using the below:
def TestEmailer(text, subject, recipient):
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = recipient
mail.Subject = subject
mail.HtmlBody = text
mail.Save()
TestEmailer('hello world', 'test', 'recipient#gmail.com')
Thanks to this previous question I can see that the SendUsingAccount() method can be used to send from a defined mailbox. Is there an equivalent method for saving to the drafts folder of a defined mailbox?
You can select Save () when you switch your account to send email, which will be saved in the draft box of the new account.
Code:
import win32com.client as win32
def send_mail():
outlook_app = win32.Dispatch('Outlook.Application')
# choose sender account
send_account = None
for account in outlook_app.Session.Accounts:
if account.DisplayName == 'sender#hotmail.com':
send_account = account
break
mail_item = outlook_app.CreateItem(0) # 0: olMailItem
# mail_item.SendUsingAccount = send_account not working
# the following statement performs the function instead
mail_item._oleobj_.Invoke(*(64209, 0, 8, 0, send_account))
mail_item.Recipients.Add('receipient#outlook.com')
mail_item.Subject = 'Test sending using particular account'
mail_item.BodyFormat = 2 # 2: Html format
mail_item.HTMLBody = '''
<H2>Hello, This is a test mail.</H2>
Hello Guys.
'''
mail_item.Save()
if __name__ == '__main__':
send_mail()
Here's a bit of black magic here. Setting mail_item.SendUsingAccount directly won't work. The return value is none. Always send mail from the first email account. You need to call the method of oleobj_.Invoke().
Updated:
Oleobj document: https://github.com/decalage2/oletools/wiki/oleobj
Similar case: python win32com outlook 2013 SendUsingAccount return exception
im complete new to this so sorry if this is a stupid question.
Im already searching the whole day for a solution of our problem.
Our Problem: We create an order for our supplier using our ERP software. The supplier want a specific subject in this email to get the mail picked up by there order receive system. We can't set the subject in out ERP software.
Workaround: ERP is sending the mail to an internal address and then we need to change the subject and forward it to the supplier.
We want to do this automatically. is this possible?
I saw a few thing about Python to do this, but not the complete solution. So i know its maybe very nooby, but who can and want to help me.
We are using Novell mail server. (that's also complete new for me :-( )
Update: i've created some code, but its not the best. :)
import smtplib, imaplib, email, re
#mail read, change and forward
imap_host = "SERVERNAME"
client = imaplib.IMAP4('SERVERNAME')
client.login('USERNAME', 'PWD')
client.select('INBOX') #, readonly=True
msgid = 1
status, data = client.fetch(msgid, "(RFC822)")
email_data = data[0][1]
client.close()
client.logout()
message = email.message_from_string(email_data)
message.replace_header("Subject", "test")
message.replace_header("From", 'test#test.com')
message.replace_header("To", 'EXTERN EMAILADRES')
smtp = smtplib.SMTP('SMTP SERVER')
smtp.starttls()
smtp.login('USERNAME', 'PWD')
from_addr = "AFZENDADRES"
to_addr = "EXTERN EMAILADRES"
smtp.sendmail(from_addr, to_addr, message.as_string())
#move mail to folder
client = imaplib.IMAP4('SERVERNAME')
client.login('USERNAME', 'PWD')
client.select('INBOX', readonly=False)
pattern_uid = re.compile('\d+ \(UID (?P<uid>\d+)\)')
def parse_uid(data):
match = pattern_uid.match(data)
return match.group('uid')
resp, items = client.search(None, 'All')
email_ids = items[0].split()
latest_email_id = email_ids[0]
resp, data = client.fetch(latest_email_id, "(UID)")
msg_uid = parse_uid(data[0])
result = client.uid('COPY', msg_uid, 'INBOX/Afgehandeld')
if result[0] == 'OK':
mov, data = client.uid('STORE', msg_uid , '+FLAGS', '(\Deleted)')
client.expunge()
client.close()
client.logout()
Should be fine if this code can be updates so that it checks if there are mails from a sender or with some words in the subject. if there aren't then stop the script. If there are 1 or more mails then we need to change the subject and forward the email to our supplier. Who can help me to get this code better.
I am using this code:
import imaplib
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login(myusername, mypassword)
mail.list()
# Out: list of "folders" aka labels in gmail.
mail.select("inbox") # connect to inbox.
result, data = mail.search(None, "ALL")
ids = data[0] # data is a list.
id_list = ids.split() # ids is a space separated string
latest_email_id = id_list[-1] # get the latest
result, data = mail.fetch(latest_email_id, "(RFC822)") # fetch the email body (RFC822) for the given ID
raw_email = data[0][1] # here's the body, which is raw text of the whole email
# including headers and alternate payloads
print raw_email
and it works, except, when I print raw_email it returns a bunch of extra information, how can I, parse, per say, the extra information and get just the From and body text?
Python's email package is probably a good place to start.
import email
msg = email.message_from_string(raw_email)
print msg['From']
print msg.get_payload(decode=True)
That should do ask you ask, though when an email has multiple parts (attachments, text and HTML versions of the body, etc.) things are a bit more complicated.
In that case, msg.is_multipart() will return True and msg.get_payload() will return a list instead of a string. There's a lot more information in the email.message documentation.
Alternately, rather than parsing the raw RFC822-formatted message - which could be very large, if the email contains attachments - you could just ask the IMAP server for the information you want. Changing your mail.fetch line to:
mail.fetch(latest_email_id, "(BODY[HEADER.FIELDS (FROM)])")
Would just request (and return) the From line of the email from the server. Likewise setting the second parameter to "(UID BODY[TEXT])" would return the body of the email. RFC2060 has a list of parameters that should be valid here.
IMAP high level lib: https://github.com/ikvk/imap_tools (I am author)
from imap_tools import MailBox, A
with MailBox('imap.mail.com').login('test#mail.com', 'password', 'INBOX') as mailbox:
for msg in mailbox.fetch(A(all=True)):
sender = msg.from_
body = msg.text or msg.html
Alternatively, you can use Red Box (I'm the author):
from redbox import EmailBox
# Create email box instance
box = EmailBox(
host="imap.example.com",
port=993,
username="me#example.com",
password="<PASSWORD>"
)
# Select an email folder
inbox = box["INBOX"]
# Search and process messages
for msg in inbox.search(all=True):
# Process the message
print(msg.from_)
print(msg.to)
print(msg.subject)
print(msg.text_body)
print(msg.html_body)
Some relevant links in the documentations:
More about querying
More about manipulating the message
More about configuring the email box
To install:
pip install redbox
Links:
Source code
Documentation