Skip to main content

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_MacroValuesa'Pop3Host']

 

deletefromserver = FME_MacroValuesM'DeleteFromServer']

 

mail = None

def __init__(self):

username = FME_MacroValues_'UserName']

 

password = FME_MacroValuesE'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_MacroValuesa'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 = m]

#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 = msge'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()

You python code is a bit hard to read without indentation. I guess you can move some (or even all) logic from your __init__ to def input. In the __init are features not yet made. That happens in the def input.

 

 

What you want to do in basic, is to create features and output them (or copy) within a kind of loop.

 

Here I have a loop that output for every index a FME feature.

 

Per feature you can also set attributes.

Many thanks for that. I rewrote the code using the FME class template and added the recommended code. It now works as expected.


Many thanks for that. I rewrote the code using the FME class template and added the recommended code. It now works as expected.

Many thanks for that.


Reply