我是Python的新手,它试图构建一个电子邮件提取器,该提取器从dialogflow的bot接收输入,然后将请求发送到我的python webhook。我想从以请求形式发送的Dialogflow的已处理输入中提取信息,以使用提取的信息进一步从服务器提取电子邮件。
我基本上要面对的问题是,默认情况下,通过Dialogflow发送的请求的超时为5秒,整个处理过程要花更多的时间。 截至目前,我正在同步进行,因此超时。我发现可以通过Python中的asyncio来完成,但不了解如何为Flask应用程序实现同样的功能。
Main.py
from imap import ImapClient
import pandas as pd
import argparse
from flask import Flask, jsonify, make_response, request
import requests
from pprint import pprint
import datetime
app = Flask(__name__)
@app.route('/')
def index():
return ('Hello World')
# @app.route('/webhook')
# def hello():
# return ('Hello World')
def results():
# build a request object
req = request.get_json(force=True)
pprint(req)
# fetch action from json
action = req.get('queryResult').get('action')
date = req.get('queryResult').get('parameters').get('date')
# guests =
# time =
print(date)
# return a fulfillment response
return {'fulfillmentText': 'Extracting mails for you....'}
def extractParam():
req = request.get_json(force=True)
date = req.get('queryResult').get('parameters').get('date')
return (date)
# create a route for webhook
@app.route('/webhook', methods=['GET', 'POST'])
def webhook():
# return response
date = extractParam()
#print('Date is', date)
#print(datetime.datetime.now())
main(date)
#print('CHCEKINGGGGG',datetime.datetime.now())
return (make_response(jsonify(results())))
def main(date_rec):
"""
You will need to store your email password in your environment, e.g.
export mailpwd=password
"""
# parser = argparse.ArgumentParser()
# parser.add_argument('uid', help='User ID to login')
# parser.add_argument('pwd', help='Password')
# parser.add_argument('rid', help='Extracting Mail address')
# args = parser.parse_args()
#print(args.uid, args.pwd)
data_unformatted = date_rec
mon = {'01':'Jan', '02':'Feb', '03':'Mar', '04':'Apr', '05':'May',
'06':'Jun', '07':'Jul', '08':'Aug', '09':'Sep', '10':'Oct',
'11':'Nov', '12':'Dec'}
data_unformatted = data_unformatted.split('-')
year = data_unformatted[0]
month = mon[data_unformatted[1]]
date = data_unformatted[2][0:2]
now = datetime.datetime.now()
if int(year) > now.year:
year = str(now.year)
final_date = ('{}-{}-{}').format(date, month, year)
print('Proceseed date is',final_date)
imap = ImapClient(recipient='<emailid>')
imap.login('<PWD>')
# retrieve messages from a given sender
messages, subjects = imap.get_messages(sender='<senderEmailID>', date=final_date)
# Do something with the messages
print("Messages in my inbox:")
lis = []
for msg in messages:
# msg is a dict of {'num': num, 'body': body}
lis.append(msg['body'])
# you could delete them after viewing
# imap.delete_message(msg['num'])
# when done, you should log out
imap.logout()
d= {'Subject': subjects, 'Body': lis}
df = pd.DataFrame(data=d)
print(df)
df.to_excel('Messages.xlsx', index=None)
return
if __name__ == "__main__":
#main()
app.run()
imap.py
import email
import email.header
import imaplib
import os
import sys
class ImapClient:
imap = None
def __init__(self,
recipient,
server='<mailServerAddress>',
use_ssl=True,
move_to_trash=True):
# check for required param
if not recipient:
raise ValueError('You must provide a recipient email address')
self.recipient = recipient
self.use_ssl = use_ssl
self.move_to_trash = move_to_trash
self.recipient_folder = 'INBOX'
# instantiate our IMAP client object
if self.use_ssl:
self.imap = imaplib.IMAP4_SSL(server)
else:
self.imap = imaplib.IMAP4(server)
def login(self, pwd):
try:
print('Trying loggin with {} username and {} password'.format(self.recipient, pwd))
rv, data = self.imap.login(self.recipient,password=pwd)
except (imaplib.IMAP4_SSL.error, imaplib.IMAP4.error) as err:
print('LOGIN FAILED!')
print(err)
sys.exit(1)
def logout(self):
self.imap.close()
self.imap.logout()
def select_folder(self, folder):
"""
Select the IMAP folder to read messages from. By default
the class will read from the INBOX folder
"""
self.recipient_folder = folder
def get_messages(self, sender, date='', subject=''):
"""
Scans for email messages from the given sender and optionally
with the given subject
:param sender Email address of sender of messages you're searching for
:param subject (Partial) subject line to scan for
:return List of dicts of {'num': num, 'body': body}
"""
if not sender:
raise ValueError('You must provide a sender email address')
print('Extracting mail from', sender)
# select the folder, by default INBOX
resp, _ = self.imap.select(self.recipient_folder)
if resp != 'OK':
print(f"ERROR: Unable to open the {self.recipient_folder} folder")
sys.exit(1)
messages = []
subject_mail = []
print('Searching for', date)
mbox_response, msgnums = self.imap.search(None, 'SENTON', date)
if mbox_response == 'OK':
for num in msgnums[0].split():
retval, rawmsg = self.imap.fetch(num, '(RFC822)')
if retval != 'OK':
print('ERROR getting message', num)
continue
msg = email.message_from_bytes(rawmsg[0][1])
msg_subject = msg["Subject"]
subject_mail.append(msg_subject)
if subject in msg_subject:
body = ""
if msg.is_multipart():
for part in msg.walk():
type = part.get_content_type()
disp = str(part.get('Content-Disposition'))
# look for plain text parts, but skip attachments
if type == 'text/plain' and 'attachment' not in disp:
charset = part.get_content_charset()
# decode the base64 unicode bytestring into plain text
body = part.get_payload(decode=True).decode(encoding=charset, errors="ignore")
# if we've found the plain/text part, stop looping thru the parts
break
else:
# not multipart - i.e. plain text, no attachments
charset = msg.get_content_charset()
body = msg.get_payload(decode=True).decode(encoding=charset, errors="ignore")
messages.append({'num': num, 'body': body})
return messages, subject_mail
def delete_message(self, msg_id):
if not msg_id:
return
if self.move_to_trash:
# move to Trash folder
self.imap.store(msg_id, '+X-GM-LABELS', '\\Trash')
self.imap.expunge()
else:
self.imap.store(msg_id, '+FLAGS', '\\Deleted')
self.imap.expunge()