I am fairly new to FME and Python.
I have written the python script to extract emails from our outlook server. It is successfully pulling down each email from a mailbox and separating out the body, subject, attachments , etc. These I have placed into attribute elements without any issues ( code below ).
The problem I have is returning each email in the transformer as a separate row. I only get the details of the last email I am downloading. I would like each email to be returned as a dataset - eg the data inspector should show 7 rows for 7 emails.
Any assistance on how I do this thru the pythoncreator transformer would be greatly appreciated.
Many thanks
Olly
import fme
import fmeobjects
import sys
import email
import imaplib
import os
import base64
def processFeature(feature):
emails = FeatureProcessor()
emails.getEmails(feature)
class FeatureProcessor(object):
mail_server = FME_MacroValues['Pop3Host']
deletefromserver = FME_MacroValues['DeleteFromServer']
mail = None
def __init__(self):
username = FME_MacroValues['UserName']
password = FME_MacroValues['Password']
self.mail = imaplib.IMAP4_SSL( self.mail_server, 993 )
self.mail.login( username, password )
self.mail.select( 'Inbox' )
def getEmails(self, feature):
resp, data = self.mail.search(None, 'ALL' )
try:
if (resp != 'OK' ):
raise Exception('Error connecting to ' + self.mail_server + ' : ' + resp )
mail_ids = data[0]
id_list = mail_ids.split()
print('-'*20)
print(self.mail.welcome)
print('New Messages: %d ' % len( id_list ))
print('-'*20)
feature.setAttribute('NumberOfEmails', len( id_list ) )
#process each new email
for num in data[0].split():
typ, full_msg = self.mail.fetch(num, '(RFC822)' )
self.process_email(full_msg, num, feature)
except:
print('Error: {0}'.format(sys.exc_info()[0]))
def get_email_body( self, email_message):
if email_message.is_multipart():
for p in email_message.walk():
if p.get_content_type() == 'text/plain' and 'attachment' not in str( p.get( 'Content-Disposition' ) ):
return p.get_payload(decode=True)
else:
return email_message.get_payload(decode=True)
def get_email_attachments(self, email_message):
SaveAttachmentsDirectory = FME_MacroValues['SaveAttachmentsDirectory']
attachments = []
for part in email_message.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
fileName = part.get_filename()
attachments.append( fileName )
if bool(fileName):
filePath = os.path.join( SaveAttachmentsDirectory , fileName)
if not os.path.isfile(filePath) :
fp = open(filePath, 'wb')
fp.write(part.get_payload(decode=True))
fp.close()
#print( 'Attachments extracted: ', attachments )
if attachments == None :
return ""
else:
return attachments
def process_email(self, full_msg, num, feature):
raw_email = full_msg[0][1] # converts byte literal to string removing b''
raw_email_string = raw_email.decode('utf-8')
email_message = email.message_from_string(raw_email_string)
msg_subject = None
msg_from = None
msg_body = None
msg_attachments = []
#other email meta data
for response_part in full_msg:
if isinstance(response_part, tuple):
msg = email.message_from_string(response_part[1].decode('utf-8'))
msg_subject = msg['subject']
msg_from = msg['from']
print('Downloading message : ' + str(num) + ' titled: ' + msg_subject )
msg_body = self.get_email_body( email_message )
msg_attachments = self.get_email_attachments( email_message )
feature.setAttribute('from', msg_from)
feature.setAttribute('subject', msg_subject)
feature.setAttribute('attachments', msg_attachments )
feature.setAttribute('body', msg_body.decode('utf-8') )
return
def input(self,feature):
self.pyoutput(feature)
def close(self):
# mailbox cleanup and close and logout session
if self.deletefromserver == 'Yes':
self.mail.expunge()
self.mail.close()
self.mail.logout()