S_208FMF
* ===================================================================
*
* Component : S_208FMF
* Type : Form
* Ancestor : PRIM_FORM
*
* Description : Main Email Message Processor
*
* Disclaimer : The following material is supplied as example material
* only. No warranty concerning this material or its use
* in any way whatsoever is expressed or implied.
*
* ===================================================================
FUNCTION OPTIONS(*DIRECT)
BEGIN_COM FORMPOSITION(ScreenCenter) HEIGHT(415) LAYOUTMANAGER(#SPLM_1) LEFT(422) TOP(24) VISUALSTYLE(#VS_NORM) WIDTH(520)
* Main form layout details
DEFINE_COM CLASS(#PRIM_SPLM) NAME(#SPLM_1)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#TOP_PANEL) DISPLAYPOSITION(3) HEIGHT(156) LEFT(0) PARENT(#COM_OWNER) TABPOSITION(3) TABSTOP(False) TOP(0) WIDTH(512)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#BOTTOM_PANEL) DISPLAYPOSITION(4) HEIGHT(228) LAYOUTMANAGER(#SPLM_2) LEFT(0) PARENT(#COM_OWNER) TABPOSITION(4) TABSTOP(False) TOP(160) WIDTH(512)
DEFINE_COM CLASS(#PRIM_SPLI) NAME(#SPLI_1) MANAGE(#TOP_PANEL) PARENT(#SPLM_1) WEIGHT(1)
DEFINE_COM CLASS(#PRIM_SPLI) NAME(#SPLI_2) MANAGE(#BOTTOM_PANEL) PARENT(#SPLM_1)
DEFINE_COM CLASS(#PRIM_SPLM) NAME(#SPLM_2) DIVIDERSTYLE(Gap) ORIENTATION(Vertical)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#LEFT_BOTTOM_PANEL) DISPLAYPOSITION(1) HEIGHT(228) LAYOUTMANAGER(#ATLM_2) LEFT(0) PARENT(#BOTTOM_PANEL) TABPOSITION(1) TABSTOP(False) TOP(0) WIDTH(226)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#RIGHT_BOTTOM_PANEL) DISPLAYPOSITION(2) HEIGHT(228) LAYOUTMANAGER(#ATLM_1) LEFT(230) PARENT(#BOTTOM_PANEL) TABPOSITION(2) TABSTOP(False) TOP(0) WIDTH(282)
DEFINE_COM CLASS(#PRIM_SPLI) NAME(#SPLI_3) MANAGE(#LEFT_BOTTOM_PANEL) PARENT(#SPLM_2)
DEFINE_COM CLASS(#PRIM_SPLI) NAME(#SPLI_4) MANAGE(#RIGHT_BOTTOM_PANEL) PARENT(#SPLM_2) WEIGHT(1)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_1) CAPTION('To start this example please follow these instructions:') DISPLAYPOSITION(1) HEIGHT(20) LEFT(4) PARENT(#TOP_PANEL) TABPOSITION(1) TABSTOP(False) TOP(4) WIDTH(261)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_2) CAPTION('(1) Start you email system (eg: MS-Outlook) running') DISPLAYPOSITION(2) HEIGHT(20) LEFT(30) PARENT(#TOP_PANEL) TABPOSITION(2) TABSTOP(False) TOP(23) WIDTH(250)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_3) CAPTION('(2) Connect to to your iSeries Server system ----------------->') DISPLAYPOSITION(3) HEIGHT(20) LEFT(30) PARENT(#TOP_PANEL) TABPOSITION(3) TABSTOP(False) TOP(45) WIDTH(267)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_4) CAPTION('(3) Connect to your email system ---------------------------------->') DISPLAYPOSITION(4) HEIGHT(20) LEFT(30) PARENT(#TOP_PANEL) TABPOSITION(4) TABSTOP(False) TOP(67) WIDTH(267)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_5) CAPTION('(4) Start processing inbound emails ------------------------------> ') DISPLAYPOSITION(5) HEIGHT(20) LEFT(30) PARENT(#TOP_PANEL) TABPOSITION(5) TABSTOP(False) TOP(88) WIDTH(267)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_6) CAPTION('(5) Leave this application running (minimized if desired) ') DISPLAYPOSITION(6) HEIGHT(20) LEFT(30) PARENT(#TOP_PANEL) TABPOSITION(6) TABSTOP(False) TOP(111) WIDTH(267)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_7) CAPTION('(6) Send emails containing attachments to your inbox ') DISPLAYPOSITION(7) HEIGHT(20) LEFT(30) PARENT(#TOP_PANEL) TABPOSITION(7) TABSTOP(False) TOP(133) WIDTH(258)
DEFINE_COM CLASS(#PRIM_ATLM) NAME(#ATLM_1) MARGINTOP(4)
DEFINE_COM CLASS(#PRIM_ATLM) NAME(#ATLM_2) MARGINTOP(4)
DEFINE_COM CLASS(#PRIM_LTVW) NAME(#EVENT_LOG) DISPLAYPOSITION(1) FULLROWSELECT(True) HEIGHT(195) LEFT(8) PARENT(#EVENT_LOG_GROUP) SELECTIONSTYLE(Single) TABPOSITION(1) TOP(21) WIDTH(210)
DEFINE_COM CLASS(#PRIM_GPBX) NAME(#EVENT_LOG_GROUP) CAPTION('Event Log') DISPLAYPOSITION(1) HEIGHT(224) LAYOUTMANAGER(#ATLM_3) LEFT(0) PARENT(#LEFT_BOTTOM_PANEL) TABPOSITION(1) TABSTOP(False) TOP(4) WIDTH(226)
DEFINE_COM CLASS(#PRIM_SPLI) NAME(#SPLI_5) MANAGE(#EVENT_LOG_GROUP) PARENT(#SPLM_1)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_3) ATTACHMENT(Center) MANAGE(#EVENT_LOG_GROUP) PARENT(#ATLM_2)
DEFINE_COM CLASS(#PRIM_ATLM) NAME(#ATLM_3) MARGINBOTTOM(4) MARGINLEFT(4) MARGINRIGHT(4) MARGINTOP(8)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_4) ATTACHMENT(Center) MANAGE(#EVENT_LOG) PARENT(#ATLM_3)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_1) ATTACHMENT(Center) MANAGE(#EVENT_LOG) PARENT(#ATLM_2)
DEFINE_COM CLASS(#PRIM_LVCL) NAME(#LVCL_1) CAPTION('Event ') CAPTIONTYPE(Caption) DISPLAYPOSITION(2) PARENT(#EVENT_LOG) SOURCE(#SYSVAR$AV) WIDTH(20) WIDTHTYPE(Remainder)
DEFINE_COM CLASS(#PRIM_LVCL) NAME(#LVCL_2) CAPTION('Time') CAPTIONTYPE(Caption) DISPLAYPOSITION(1) PARENT(#EVENT_LOG) SOURCE(#TIME) WIDTH(25) WIDTHTYPE(Fixed)
DEFINE_COM CLASS(#PRIM_LTVW) NAME(#MAIL_LIST) DISPLAYPOSITION(1) FULLROWSELECT(True) HEIGHT(195) LEFT(8) PARENT(#MAIL_LIST_GROUP) SELECTIONSTYLE(Single) TABPOSITION(1) TOP(21) WIDTH(266)
DEFINE_COM CLASS(#PRIM_GPBX) NAME(#MAIL_LIST_GROUP) CAPTION('Currently Selected Emails') DISPLAYPOSITION(1) HEIGHT(224) LAYOUTMANAGER(#ATLM_4) LEFT(0) PARENT(#RIGHT_BOTTOM_PANEL) TABPOSITION(1) TABSTOP(False) TOP(4) WIDTH(282)
DEFINE_COM CLASS(#PRIM_SPLI) NAME(#SPLI_6) MANAGE(#MAIL_LIST_GROUP) PARENT(#SPLM_1)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_5) ATTACHMENT(Center) MANAGE(#MAIL_LIST_GROUP) PARENT(#ATLM_1)
DEFINE_COM CLASS(#PRIM_ATLM) NAME(#ATLM_4) MARGINBOTTOM(4) MARGINLEFT(4) MARGINRIGHT(4) MARGINTOP(8)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_6) ATTACHMENT(Center) MANAGE(#MAIL_LIST) PARENT(#ATLM_4)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_2) ATTACHMENT(Center) MANAGE(#MAIL_LIST) PARENT(#ATLM_1)
DEFINE_COM CLASS(#PRIM_LVCL) NAME(#LVCL_3) CAPTION('Subject') CAPTIONTYPE(Caption) DISPLAYPOSITION(1) PARENT(#MAIL_LIST) SOURCE(#SYSVAR$AV) WIDTH(34)
DEFINE_COM CLASS(#PRIM_LVCL) NAME(#LVCL_4) CAPTION('From') CAPTIONTYPE(Caption) DISPLAYPOSITION(2) PARENT(#MAIL_LIST) SOURCE(#STD_TEXTL) WIDTH(34)
DEFINE_COM CLASS(#PRIM_LVCL) NAME(#LVCL_6) CAPTION('Received') CAPTIONTYPE(Caption) DISPLAYPOSITION(3) PARENT(#MAIL_LIST) SOURCE(#STD_DESC) WIDTH(20) WIDTHTYPE(Remainder)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#CONNECT_SERVER_PANEL) DISPLAYPOSITION(9) HEIGHT(137) LEFT(300) PARENT(#TOP_PANEL) TABPOSITION(8) TABSTOP(False) TOP(8) WIDTH(213)
DEFINE_COM CLASS(#PRIM_PHBN) NAME(#CONNECT_SERVER) CAPTION('Connect to iSeries Server System') DISPLAYPOSITION(1) LEFT(16) PARENT(#CONNECT_SERVER_PANEL) TABPOSITION(1) TOP(32) WIDTH(172)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#CONNECT_MAIL_PANEL) DISPLAYPOSITION(8) HEIGHT(129) LEFT(300) PARENT(#TOP_PANEL) TABPOSITION(10) TABSTOP(False) TOP(16) VISIBLE(False) WIDTH(205)
DEFINE_COM CLASS(#PRIM_PHBN) NAME(#CONNECT_MAIL) CAPTION('Connect to Email System') DISPLAYPOSITION(1) LEFT(16) PARENT(#CONNECT_MAIL_PANEL) TABPOSITION(1) TOP(48) WIDTH(172)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#START_POLLING_PANEL) DISPLAYPOSITION(10) HEIGHT(129) LEFT(300) PARENT(#TOP_PANEL) TABPOSITION(9) TABSTOP(False) TOP(16) VISIBLE(False) WIDTH(205)
DEFINE_COM CLASS(#PRIM_PHBN) NAME(#START_POLLING) CAPTION('Start processing inbound emails') DISPLAYPOSITION(1) LEFT(16) PARENT(#START_POLLING_PANEL) TABPOSITION(1) TOP(66) WIDTH(172)
DEFINE_COM CLASS(#STD_NUM.Visual) NAME(#MAIL_POLLING_TIME) DISPLAYPOSITION(3) HEIGHT(19) LEFT(118) MARGINLEFT(0) PARENT(#START_POLLING_PANEL) TABPOSITION(3) TOP(95) WIDTH(37)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_8) CAPTION('seconds') DISPLAYPOSITION(2) HEIGHT(19) LEFT(158) PARENT(#START_POLLING_PANEL) TABPOSITION(2) TABSTOP(False) TOP(97) WIDTH(48)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_9) CAPTION('Check for email every') DISPLAYPOSITION(4) HEIGHT(19) LEFT(8) PARENT(#START_POLLING_PANEL) TABPOSITION(4) TABSTOP(False) TOP(97) WIDTH(106)
* The AS/400 Server connection object
DEFINE_COM CLASS(#VL_SAM003) NAME(#SERVER)
* Email session and messages objects
DEFINE_COM CLASS(#S_208XSO.MAPISession) NAME(#MAIL_SESSION) reference(*Dynamic)
DEFINE_COM CLASS(#S_208XMO.MAPIMessages) NAME(#INBOUND_MAIL) reference(*Dynamic)
DEFINE_COM CLASS(#S_208XMO.MAPIMessages) NAME(#OUTBOUND_MAIL) reference(*Dynamic)
* The Email polling timer
DEFINE_COM CLASS(#PRIM_TIMR) NAME(#MAIL_POLLING_TIMER) INTERVAL(0)
* The MS-Word document handler
DEFINE_COM CLASS(#S_208RMW) NAME(#MS_WORD) DISPLAYPOSITION(2) PARENT(#COM_OWNER) TABPOSITION(2) VISIBLE(False)
* The MS-Excel document handler
DEFINE_COM CLASS(#S_208RME) NAME(#MS_EXCEL) PARENT(#COM_OWNER) VISIBLE(False)
* Lists used to store names and values extracted from MS-Word or MS-Excel documents
Def_list #List01 (#S_208Name #S_208Inst #S_208AVal #S_208NVal) Type(*Working) Entrys(100)
Def_list #List02 (#S_208Name #S_208Inst #S_208AVal #S_208NVal) Type(*Working) Entrys(100)
Def_list #List03 (#S_208Name #S_208Inst #S_208AVal #S_208NVal) Type(*Working) Entrys(100)
Def_list #List04 (#S_208Name #S_208Inst #S_208AVal #S_208NVal) Type(*Working) Entrys(100)
Def_list #List05 (#S_208Name #S_208Inst #S_208AVal #S_208NVal) Type(*Working) Entrys(100)
* List used to get messages back from the server
Define #MessCount Reffld(#ListCount)
Def_List Name(#MESSAGES) Fields(#S_208MSG) Counter(#MESSCOUNT) Type(*WORKING) Entrys(9999)
* Lists used to get spool file details back from the server
DEF_LIST NAME(#SPOOL01) FIELDS(#S_208MSG) TYPE(*WORKING) ENTRYS(240)
DEF_LIST NAME(#SPOOL02) FIELDS(#S_208MSG) TYPE(*WORKING) ENTRYS(240)
DEF_LIST NAME(#SPOOL03) FIELDS(#S_208MSG) TYPE(*WORKING) ENTRYS(240)
DEF_LIST NAME(#SPOOL04) FIELDS(#S_208MSG) TYPE(*WORKING) ENTRYS(240)
* Global flag to store the name of function to be called on the
* the server system to process a document has been found in the
* data extracted from a MS-Word or MS-Excel document
DEFINE_COM CLASS(#STD_OBJ) NAME(#RDML_FUNCTION)
* The event that signals that some documentation information has been found
* (also see S_208RMW and S_208RME that also signal this message)
Define_Evt InformationFound
Define_Map *input #S_208Name #WithName
Define_Map *input #S_208AVAL #WithValue
* ===============================
* Handle main form initialization
* ===============================
EVTROUTINE handling(#com_owner.Initialize)
* Set up the form caption and initalize other variables
SET #com_owner caption(*component_desc)
* Log the form start up to the event log
Invoke #Com_Owner.Log EventText(*component_desc) EventText2('started')
* Create and initialize the MAPI email session
Set_Ref #MAIL_SESSION (*Create_as #S_208XSO.MAPISession)
Set #MAIL_SESSION Parent(#Com_Owner)
Invoke #Mail_Session.Realize
* Create and initialize the MAPI email message handler for inbound mail
Set_Ref #INBOUND_MAIL (*Create_as #S_208XMO.MAPIMessages)
Set #Inbound_Mail Parent(#Com_Owner)
Invoke #Inbound_Mail.Realize
* Create and initialize the MAPI email message handler for outbound mail
Set_Ref #OUTBOUND_MAIL (*Create_as #S_208XMO.MAPIMessages)
Set #Outbound_Mail Parent(#Com_Owner)
Invoke #Outbound_Mail.Realize
ENDROUTINE
* ========================
* Handle main form closing
* ========================
EVTROUTINE handling(#com_owner.Closing)
* Disconnect the AS/400 server
Invoke #Server.uDisconnect
* Shutdown the MS-Word document handler
Invoke #MS_Word.Shutdown
* Shutdown the MS-Excel document handler
Invoke #MS_Excel.Shutdown
* Disconnect from the mail server
If '#Mail_Session.SessionId *ne 0'
Invoke #Mail_Session.SignOff
Endif
* Destroy all of the MAPI email objects
Invoke #OutBound_Mail.unRealize
Invoke #InBound_Mail.unRealize
Invoke #Mail_Session.unRealize
Set_Ref #OutBound_Mail *null
Set_Ref #InBound_Mail *null
Set_Ref #Mail_Session *null
ENDROUTINE
* ================================================
* Handle a request to connect to the AS/400 server
* ================================================
EVTROUTINE HANDLING(#CONNECT_SERVER.Click)
Invoke #Com_Owner.Log EventText('Connecting to iSeries server system')
INVOKE METHOD(#SERVER.uConnectModal)
ENDROUTINE
* =====================================================================
* Handle a server connection creation signalled by #SERVER (#VL_SAM003)
* =====================================================================
EVTROUTINE HANDLING(#SERVER.uConnectionCreated)
Invoke #Com_Owner.Log EventText('Now connected to iSeries server system')
* Make the connect to AS/400 server panel invisible
Set #Connect_Server_panel Visible(False)
* Now make the connect to email server panel visible
Set #Connect_Mail_panel Visible(True)
ENDROUTINE
* ===================================================
* Handle a request to connect to the to email system
* ===================================================
EVTROUTINE HANDLING(#CONNECT_Mail.Click)
* Logon / Connect to the email system
Invoke #Com_Owner.Log EventText('Signing on to email system')
Set #Mail_Session LogonUI(True)
Invoke #Mail_Session.Signon
* Link the mail inbound and outbound email sessions to the connection
Set #InBound_Mail SessionId(#Mail_Session.SessionId)
Set #OutBound_Mail SessionId(#Mail_Session.SessionId)
Invoke #Com_Owner.Log EventText('Signed on to email system')
* Make the connect to email server panel invisible
Set #Connect_Mail_panel Visible(False)
* Make the start processing email panel visible
* and set a default value for the polling time
Set #Start_Polling_panel Visible(True)
Set #Mail_Polling_Time Value(30)
ENDROUTINE
* ========================================================
* Check that the email pollng time specified is "sensible"
* ========================================================
EVTROUTINE HANDLING(#Mail_Polling_Time.LostFocus) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS)
Change #Std_Num #Mail_Polling_Time.Value
* If less then 10 set to 10, if greater than 600 set to 600
Case #Std_Num
When '< 10'
Set #Mail_Polling_Time Value(10)
When '> 600'
Set #Mail_Polling_Time Value(600)
EndCase
ENDROUTINE
* =============================================================
* Handle a request to start polling/checking for email messages
* =============================================================
EVTROUTINE HANDLING(#Start_Polling.Click)
* Make the start processing email panel invisible
Set #Start_Polling_Panel Visible(False)
* Make all the connection details and instructions at the top
* of the main form disappear
Set #Top_Panel Visible(False)
* Start the mail polling timer running (see #Mail_Polling_Timer.Tick)
Set #Mail_Polling_Timer Interval(1)
ENDROUTINE
* =================================================
* Handle a tick of the mail polling timer
* (ie: It's time to check for newly arrived email)
* =================================================
EVTROUTINE HANDLING(#Mail_Polling_Timer.Tick) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS)
Define #A_Limit Reffld(#Std_Num) Desc('Count of inbound emails')
Define #A_Index Reffld(#Std_Num) Desc('Loop index for inbound messages loop')
Define #MsgIndex Reffld(#Std_Num) Desc('Index to current inbound email')
* Stop the timer
Set #Mail_Polling_Timer Interval(0)
* Log a starting message
Invoke #Com_Owner.Log EventText('Checking for new emails')
* Fetch an updated email list from the Inbox
Invoke #InBound_Mail.Fetch
* Loop through all email messages currently in the InBox
Clr_List #Mail_List
Change #A_Limit #InBound_Mail.MsgCount
Begin_Loop from(1) to(#A_Limit) Using(#A_Index)
Change #MsgIndex '#A_Index - 1'
* Set the index to the current email message details
Set #InBound_Mail MsgIndex(#MsgIndex)
* Skip this message if it's already been read or if it has no attachments
Continue '(#InBound_Mail.MsgRead = True) or (#InBound_Mail.AttachmentCount <= 0)'
* Assemble the message details to place into the visible list
Change #SysVar$Av #InBound_Mail.MsgSubject
Change #Std_TextL #InBound_Mail.MsgOrigDisplayName
Change #Std_Desc #InBound_Mail.MsgDateReceived
* Add an entry to the mail list visible on the mail form
Add_Entry #Mail_List
* Loop around and process the next message
End_Loop
* Log a completion message
Invoke #Com_Owner.Log EventText('Finished checking for new emails')
* Update the display of the mail details on the main form so that they become immediately visible
Invoke #Mail_List_Group.UpdateDisplay
* Now do a second pass through the messages and pick out all unread
* messages that have attachments. These are eligible for processing
Invoke #Com_Owner.Log EventText('Now checking for unread emails with attachments')
Change #A_Limit #InBound_Mail.MsgCount
Begin_Loop from(#A_Limit) to(1) Using(#A_Index) Step(-1)
Change #MsgIndex '#A_Index - 1'
* Set the index to the current email message details
Set #InBound_Mail MsgIndex(#MsgIndex)
* Skip this message if it's already been read or if it has no attachments
Continue '(#InBound_Mail.MsgRead = True) or (#InBound_Mail.AttachmentCount <= 0)'
* We now have a message to be handled, invoke HandleAttachments to check out any attachments that this email may have
Invoke #Com_Owner.HandleAttachments
* Loop around and process the next email message
End_Loop
Invoke #Com_Owner.Log EventText('Finished checking for unread emails with attachments')
* Now restart the timer
Change #Std_Num '#Mail_Polling_Time.Value * 1000'
Set #Mail_Polling_Timer Interval(#Std_Num)
* Finished .... we'll now wait for the next tick of the timer and do it all again
ENDROUTINE
* ====================================================
* Handle all attachments in the current email message
* ====================================================
MthRoutine HandleAttachments
Define #B_Limit Reffld(#Std_Num) Desc('Loop Limit')
Define #B_Index Reffld(#Std_Num) Desc('Loop Index')
Define #AtchIndex Reffld(#Std_Num) Desc('Current Attachment Index')
Define #RetCode2 *char 2 Desc('Standard char(2) LANSA return code')
* Log start
Invoke #Com_Owner.Log EventText('Processing' ) EventText2(#InBound_Mail.MsgSubject) EventText3('from') EventText4(#InBound_Mail.MsgOrigDisplayName)
* Loop through all the attachments in the current email message
Change #B_Limit #InBound_Mail.AttachmentCount
Begin_Loop from(1) to(#B_Limit) Using(#B_Index)
Change #AtchIndex '#B_Index - 1'
Set #InBound_Mail AttachmentIndex(#AtchIndex)
* Invoke HandleDocument to handle a single document attached to the current email message
Invoke #Com_Owner.HandleDocument DocumentName(#InBound_Mail.AttachmentName) DocumentPathName(#InBound_Mail.AttachmentPathName)
End_Loop
* Log end
Invoke #Com_Owner.Log EventText('Finished processing' ) EventText2(#InBound_Mail.MsgSubject) EventText3('from') EventText4(#InBound_Mail.MsgOrigDisplayName)
Endroutine
* ===============================================================
* Handle a single attached document in the current email message
* ===============================================================
MthRoutine HandleDocument
Define_Map *input #SysVar$Av #DocumentName
Define_Map *input #SysVar$Av #DocumentPathName
Define #Position Type(*Dec) Length(3) decimals(0) Desc('Scan Position')
Define #Temp_File Reffld(#SysVar$av) Desc('Temporary File Name')
Def_Cond *Found '#Position > 0'
* Log attachment processing start
Invoke #Com_Owner.Log EventText('Processing attachment' ) EventText2(#DocumentName.Value) EventText3('in') EventText4(#DocumentPathName.Value)
* Clear all the storage areas and lists used betwene the client (this component)
* and the server (RDML function SET208H).
* List01 -> List05 are the values extracted from the MS-Word or MS-Excel document
Change #ListCount 0
Clr_List #List01
Clr_List #List02
Clr_List #List03
Clr_List #List04
Clr_List #List05
* Messages is the list of messages returned by the AS/400 server after
* the document has been processed. Ultimately Messages is used to form the
* text of the attachment file that is sent back to the email sender.
Clr_List #Messages
* Spool01 -> Spool04 are any spool file details that have been sent back
* by the AS/400 server. These are added to the Messages list and also
* sent back to the email sender. See RDML function SET208Q for an example
* of a function that prints a report on the server and sends the spool file
* details back in lists Spool01 -> Spool04
Clr_List #Spool01
Clr_List #Spool02
Clr_List #Spool03
Clr_List #Spool04
* Set the name of the RDML function to be called to handle this document
* to blanks to indicate that it has not been found in the document data (yet).
Set #RDML_FUNCTION Value(*Blanks)
* Now see if this attachment is a MS-Word document
Use ScanString (#DocumentName.Value '.DOC' 1 '1' '1') To_Get(#Position)
* If it is a MS-Word document invoke #MS_Word.ExtractInformation to extract all the
* book mark details from the document. The details are signalled back to this
* component by "InformationFound" events issued by #MS_Word.ExtractInformation.
If *Found
Invoke #Com_Owner.Log EventText('Found MS-Word document' ) EventText2(#DocumentName.Value)
Invoke #MS_Word.ExtractInformation FromDocument(#DocumentPathName.Value)
Else
* If not a MS-Word document, see if this attachment is a MS-Excel document
Use ScanString (#DocumentName.Value '.XLS' 1 '1' '1') To_Get(#Position)
* If it is a MS-Word document invoke #MS_Excel.ExtractInformation to extract all the
* speadsheet cell details from the document. The details are signalled back to this
* component by "InformationFound" events issued by #MS_Excel.ExtractInformation.
If *Found
Invoke #Com_Owner.Log EventText('Found MS-Excel document' ) EventText2(#DocumentName.Value)
Invoke #MS_Excel.ExtractInformation FromDocument(#DocumentPathName.Value)
Endif
Endif
* If something was added to one of the lists by one of the information
* extractors (ie: #MS_Word.ExtractInformation or #MS_Excel.ExtractInformation)
* we need to place a call to the AS/400 server application to process the
* extracted details ....
If '#ListCount > 0'
* If the name of the RDML function to be used on the server to process
* the information extracted from the document has not been found in
* the document set a default value from the first 7 characters of the
* attachment file name .....
If '#RDML_Function.Value = *Blanks'
Define #TmpChar07 *char 7
Change #TmpChar07 #DocumentName.Value
Signal InformationFound WithName(RDML_FUNCTION) WithValue(#TmpChar07)
Endif
* Log an event identifying the RDML function that will used to handle the document on the server system
Invoke #Com_Owner.Log EventText('RDML function' ) EventText2(#RDML_Function.Value) EventText3('will be used to handle document') EventText4(#DocumentName.Value)
* Do the call to the remote procedure. Call RDML function SET208H which will manage details of calling the handling RDML function specified in #RDML_Function.Value
USE CALL_SERVER_FUNCTION WITH_ARGS(*SSERVER_SSN SET208H N Y #LIST01 #LIST02 #LIST03 #LIST04 #LIST05 #Messages #Spool01 #Spool02 #Spool03 #Spool04) TO_GET(#RetCode2)
* If the call to RDML function SET208H failed, log an error into the event log
If '#RetCode2 *ne OK'
Invoke #Com_Owner.Log EventText('***ERROR*** Call to server message handler failed.' )
Endif
* Now collect any messages on the current message queue and add them to the message list and then clear the message queue
Use Get_Message To_Get(#RetCode2 #S_208Msg)
Dowhile '(#MessCount < 9999) and (#RetCode2 = OK)'
Add_Entry #Messages
Use Get_Message To_Get(#RetCode2 #S_208Msg)
EndWhile
Use Clr_Messages
* Now collect any returned spool file lines and place them into the message list as well
SelectList #Spool01
Add_Entry #Messages
EndSelect
SelectList #Spool02
Add_Entry #Messages
EndSelect
SelectList #Spool03
Add_Entry #Messages
EndSelect
SelectList #Spool04
Add_Entry #Messages
EndSelect
* Now transform the entire messages list into a temporary flat file (name is in #Temp_File)
Use tConcat (*Temp_Dir 'S_208FMF_Reply.txt') (#Temp_File)
USE BUILTIN(TRANSFORM_LIST) WITH_ARGS(#Messages #Temp_File C B T) TO_GET(#RetCode2)
* If the TRANSFORM_LIST operation failed, log an error to the event
* log and blank out the temporary file name so that it will not be
* sent as an attachment later
If '#RetCode2 *ne OK'
Invoke #Com_Owner.Log EventText('***ERROR*** Attempt to save temporary file failed.' )
Change #Temp_File *Blanks
Endif
* Now assemble the reply email
Invoke #OutBound_Mail.Compose
* Set up the addressing details
Set #OutBound_Mail RecipDisplayName(#InBound_Mail.MsgOrigDisplayName)
Set #OutBound_Mail RecipAddress(#InBound_Mail.MsgOrigAddress)
Set #OutBound_Mail AddressResolveUI(False)
* Set up the subject
Use bConcat ('Automatic Response to ->' #InBound_Mail.MsgSubject) (#SysVar$av)
Set #OutBound_Mail MsgSubJect(#SysVar$av)
* Set up the message text body
Set #OutBound_Mail MsgNoteText('Please read the attachment for response details.')
* Add the temporary messages file (if it was saved okay) to the
* email as an attachment
If '#Temp_File *ne *Blanks'
Set #OutBound_Mail AttachmentPathName(#Temp_File)
Endif
* Log an event indicating that email is about to be sent
Invoke #Com_Owner.Log EventText('Sending reply email to' ) EventText2(#OutBound_Mail.RecipDisplayName)
* Send the email message back to the original sender
Invoke #OutBound_Mail.Send vDialog(0)
Endif
* Log document processing end
Invoke #Com_Owner.Log EventText('Finished processing attachment' ) EventText2(#DocumentName.Value) EventText3('in') EventText4(#DocumentPathName.Value)
Endroutine
* ========================================================================
* Handle extracted information coming back from this component itself, the
* MS-Word information extractor or the MS-Excel information extractor
* ========================================================================
EVTROUTINE HANDLING(#COM_Owner.InformationFound #MS_Word.InformationFound #MS_Excel.InformationFound) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS) WithName(#WithName) WithValue(#WithValue)
Define #Pos *Dec 3 0
Define #Int *Dec 15 0
Define #Dec *Dec 9 9
Define #LastPos Reffld(#pos)
Define #TWithName Reffld(#S_208Name)
Define #RetCode *char 1
* Set up the default values for the entry to be stored in the lists
* that will be eventually passed to the server function SET208H
* #S_208NAME - the NAME (most commonly a MS-Word bookmark or CELL_rrrrrrr_ccccccc)
Change #S_208Name #WithName.value
Use UpperCase (#S_208Name) (#S_208Name)
* #S_208INST - the INSTANCE of the name
Change #S_208Inst 1
* #S_208AVAL - the ALPHANUMERIC value
Change #S_208AVal #WithValue.value
* #S_208NVAL - the NUMERIC value (if a conversion is possible)
Change (#Int #Dec) *Null
Use CHECKNUMERIC WITH_ARGS(#S_208AVal 15 9) TO_GET(#Int #Dec #RetCode)
Change #S_208NVal '#Int + #Dec'
* Now see if the name ends in an instance number (ie: the name is in
* the format NAME_nnnn) and if it does, extract the instance number
* and remove the instance number from the name. Thus the name
* EMPNO_56 changes #S208Inst to 56 and #S_208Name to EMPNO.
* Likewise the the name CELL_000007_00005 would be reduced
* to name CELL_000007 and instance number 5
Change #Pos 1
Change #LastPos 0
Begin_Loop
Use ScanString WITH_ARGS(#S_208Name '_' #Pos) TO_GET(#Pos)
Leave '#Pos <= 0'
Leave '#Pos >= 32'
Change #LastPos #Pos
Change #Pos '#Pos + 1'
End_Loop
If '#LastPos > 0'
Change #TWithName *Blanks
Substring (#S_208Name #LastPos) (#TWithName)
Change #Int *Null
Use CHECKNUMERIC WITH_ARGS(#TWithName 7 0 '_') TO_GET(#Int #Dec #RetCode)
If '(#RetCode = Y) and (#Int > 0)'
Change #S_208Inst #Int
Substring (#Blank) (#S_208Name #LastPos *End)
Endif
Endif
* We now should have the #S208Name, #S208Inst, #S_208Aval and #S_208NVal
* values finalized ... so add an entry to appropriate storage list.
*
* Five lists (List01 -> List05) are used here to avoid any one list being
* more than 32,000 bytes long when it is passed to the server function
* SET208H. Logically they can be thought of as a single list.
Case #ListCount
When '< 100'
Add_Entry #List01
When '< 200'
Add_Entry #List02
When '< 300'
Add_Entry #List03
When '< 400'
Add_Entry #List04
When '< 500'
Add_Entry #List05
Otherwise
Invoke #Com_Owner.Log EventText('***ERROR*** List overflow. Data ignored.') EventText2(#S_208AVal)
EndCase
* Keep a count of the total number of list entries added
Change #ListCount '#ListCount + 1'
* If the name just processed is "RDML_FUNCTION" then save the
* value. This name is used by method routine "HandleDocument" to
* decide whether it should add a default function name to the
* list of document values.
If '#S_208Name = RDML_FUNCTION'
Set #RDML_FUNCTION Value(#S_208AVal)
Endif
Endroutine
* =====================================
* Log an Event to the visible event log
* =====================================
MthRoutine Log
Define_Map *input #SysVar$Av #EventText
Define_Map *input #SysVar$Av #EventText2 Mandatory(' ')
Define_Map *input #SysVar$Av #EventText3 Mandatory(' ')
Define_Map *input #SysVar$Av #EventText4 Mandatory(' ')
* Clear the log if it has more than 200 message in it
If '#Event_Log.Entries > 200'
Clr_List #Event_Log
Endif
* Concatenate the message parts together
Use bConcat (#EventText.Value #EventText2.Value #EventText3.Value #EventText4.Value) (#SysVar$Av)
* Set the time and add an entry to the event log
Change #Time *Time
Add_Entry #Event_Log
Set #Event_Log.CurrentItem EnsureVisible(True)
* Update the display so that the event log message appears instantly
Invoke #Event_Log_Group.UpdateDisplay
Endroutine
END_COM
* ===================================================================
*
* Component : S_208FMF
* Type : Form
* Ancestor : PRIM_FORM
*
* Description : Main Email Message Processor
*
* Disclaimer : The following material is supplied as example material
* only. No warranty concerning this material or its use
* in any way whatsoever is expressed or implied.
*
* ===================================================================
FUNCTION OPTIONS(*DIRECT)
BEGIN_COM FORMPOSITION(ScreenCenter) HEIGHT(415) LAYOUTMANAGER(#SPLM_1) LEFT(422) TOP(24) VISUALSTYLE(#VS_NORM) WIDTH(520)
* Main form layout details
DEFINE_COM CLASS(#PRIM_SPLM) NAME(#SPLM_1)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#TOP_PANEL) DISPLAYPOSITION(3) HEIGHT(156) LEFT(0) PARENT(#COM_OWNER) TABPOSITION(3) TABSTOP(False) TOP(0) WIDTH(512)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#BOTTOM_PANEL) DISPLAYPOSITION(4) HEIGHT(228) LAYOUTMANAGER(#SPLM_2) LEFT(0) PARENT(#COM_OWNER) TABPOSITION(4) TABSTOP(False) TOP(160) WIDTH(512)
DEFINE_COM CLASS(#PRIM_SPLI) NAME(#SPLI_1) MANAGE(#TOP_PANEL) PARENT(#SPLM_1) WEIGHT(1)
DEFINE_COM CLASS(#PRIM_SPLI) NAME(#SPLI_2) MANAGE(#BOTTOM_PANEL) PARENT(#SPLM_1)
DEFINE_COM CLASS(#PRIM_SPLM) NAME(#SPLM_2) DIVIDERSTYLE(Gap) ORIENTATION(Vertical)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#LEFT_BOTTOM_PANEL) DISPLAYPOSITION(1) HEIGHT(228) LAYOUTMANAGER(#ATLM_2) LEFT(0) PARENT(#BOTTOM_PANEL) TABPOSITION(1) TABSTOP(False) TOP(0) WIDTH(226)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#RIGHT_BOTTOM_PANEL) DISPLAYPOSITION(2) HEIGHT(228) LAYOUTMANAGER(#ATLM_1) LEFT(230) PARENT(#BOTTOM_PANEL) TABPOSITION(2) TABSTOP(False) TOP(0) WIDTH(282)
DEFINE_COM CLASS(#PRIM_SPLI) NAME(#SPLI_3) MANAGE(#LEFT_BOTTOM_PANEL) PARENT(#SPLM_2)
DEFINE_COM CLASS(#PRIM_SPLI) NAME(#SPLI_4) MANAGE(#RIGHT_BOTTOM_PANEL) PARENT(#SPLM_2) WEIGHT(1)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_1) CAPTION('To start this example please follow these instructions:') DISPLAYPOSITION(1) HEIGHT(20) LEFT(4) PARENT(#TOP_PANEL) TABPOSITION(1) TABSTOP(False) TOP(4) WIDTH(261)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_2) CAPTION('(1) Start you email system (eg: MS-Outlook) running') DISPLAYPOSITION(2) HEIGHT(20) LEFT(30) PARENT(#TOP_PANEL) TABPOSITION(2) TABSTOP(False) TOP(23) WIDTH(250)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_3) CAPTION('(2) Connect to to your iSeries Server system ----------------->') DISPLAYPOSITION(3) HEIGHT(20) LEFT(30) PARENT(#TOP_PANEL) TABPOSITION(3) TABSTOP(False) TOP(45) WIDTH(267)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_4) CAPTION('(3) Connect to your email system ---------------------------------->') DISPLAYPOSITION(4) HEIGHT(20) LEFT(30) PARENT(#TOP_PANEL) TABPOSITION(4) TABSTOP(False) TOP(67) WIDTH(267)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_5) CAPTION('(4) Start processing inbound emails ------------------------------> ') DISPLAYPOSITION(5) HEIGHT(20) LEFT(30) PARENT(#TOP_PANEL) TABPOSITION(5) TABSTOP(False) TOP(88) WIDTH(267)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_6) CAPTION('(5) Leave this application running (minimized if desired) ') DISPLAYPOSITION(6) HEIGHT(20) LEFT(30) PARENT(#TOP_PANEL) TABPOSITION(6) TABSTOP(False) TOP(111) WIDTH(267)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_7) CAPTION('(6) Send emails containing attachments to your inbox ') DISPLAYPOSITION(7) HEIGHT(20) LEFT(30) PARENT(#TOP_PANEL) TABPOSITION(7) TABSTOP(False) TOP(133) WIDTH(258)
DEFINE_COM CLASS(#PRIM_ATLM) NAME(#ATLM_1) MARGINTOP(4)
DEFINE_COM CLASS(#PRIM_ATLM) NAME(#ATLM_2) MARGINTOP(4)
DEFINE_COM CLASS(#PRIM_LTVW) NAME(#EVENT_LOG) DISPLAYPOSITION(1) FULLROWSELECT(True) HEIGHT(195) LEFT(8) PARENT(#EVENT_LOG_GROUP) SELECTIONSTYLE(Single) TABPOSITION(1) TOP(21) WIDTH(210)
DEFINE_COM CLASS(#PRIM_GPBX) NAME(#EVENT_LOG_GROUP) CAPTION('Event Log') DISPLAYPOSITION(1) HEIGHT(224) LAYOUTMANAGER(#ATLM_3) LEFT(0) PARENT(#LEFT_BOTTOM_PANEL) TABPOSITION(1) TABSTOP(False) TOP(4) WIDTH(226)
DEFINE_COM CLASS(#PRIM_SPLI) NAME(#SPLI_5) MANAGE(#EVENT_LOG_GROUP) PARENT(#SPLM_1)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_3) ATTACHMENT(Center) MANAGE(#EVENT_LOG_GROUP) PARENT(#ATLM_2)
DEFINE_COM CLASS(#PRIM_ATLM) NAME(#ATLM_3) MARGINBOTTOM(4) MARGINLEFT(4) MARGINRIGHT(4) MARGINTOP(8)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_4) ATTACHMENT(Center) MANAGE(#EVENT_LOG) PARENT(#ATLM_3)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_1) ATTACHMENT(Center) MANAGE(#EVENT_LOG) PARENT(#ATLM_2)
DEFINE_COM CLASS(#PRIM_LVCL) NAME(#LVCL_1) CAPTION('Event ') CAPTIONTYPE(Caption) DISPLAYPOSITION(2) PARENT(#EVENT_LOG) SOURCE(#SYSVAR$AV) WIDTH(20) WIDTHTYPE(Remainder)
DEFINE_COM CLASS(#PRIM_LVCL) NAME(#LVCL_2) CAPTION('Time') CAPTIONTYPE(Caption) DISPLAYPOSITION(1) PARENT(#EVENT_LOG) SOURCE(#TIME) WIDTH(25) WIDTHTYPE(Fixed)
DEFINE_COM CLASS(#PRIM_LTVW) NAME(#MAIL_LIST) DISPLAYPOSITION(1) FULLROWSELECT(True) HEIGHT(195) LEFT(8) PARENT(#MAIL_LIST_GROUP) SELECTIONSTYLE(Single) TABPOSITION(1) TOP(21) WIDTH(266)
DEFINE_COM CLASS(#PRIM_GPBX) NAME(#MAIL_LIST_GROUP) CAPTION('Currently Selected Emails') DISPLAYPOSITION(1) HEIGHT(224) LAYOUTMANAGER(#ATLM_4) LEFT(0) PARENT(#RIGHT_BOTTOM_PANEL) TABPOSITION(1) TABSTOP(False) TOP(4) WIDTH(282)
DEFINE_COM CLASS(#PRIM_SPLI) NAME(#SPLI_6) MANAGE(#MAIL_LIST_GROUP) PARENT(#SPLM_1)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_5) ATTACHMENT(Center) MANAGE(#MAIL_LIST_GROUP) PARENT(#ATLM_1)
DEFINE_COM CLASS(#PRIM_ATLM) NAME(#ATLM_4) MARGINBOTTOM(4) MARGINLEFT(4) MARGINRIGHT(4) MARGINTOP(8)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_6) ATTACHMENT(Center) MANAGE(#MAIL_LIST) PARENT(#ATLM_4)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_2) ATTACHMENT(Center) MANAGE(#MAIL_LIST) PARENT(#ATLM_1)
DEFINE_COM CLASS(#PRIM_LVCL) NAME(#LVCL_3) CAPTION('Subject') CAPTIONTYPE(Caption) DISPLAYPOSITION(1) PARENT(#MAIL_LIST) SOURCE(#SYSVAR$AV) WIDTH(34)
DEFINE_COM CLASS(#PRIM_LVCL) NAME(#LVCL_4) CAPTION('From') CAPTIONTYPE(Caption) DISPLAYPOSITION(2) PARENT(#MAIL_LIST) SOURCE(#STD_TEXTL) WIDTH(34)
DEFINE_COM CLASS(#PRIM_LVCL) NAME(#LVCL_6) CAPTION('Received') CAPTIONTYPE(Caption) DISPLAYPOSITION(3) PARENT(#MAIL_LIST) SOURCE(#STD_DESC) WIDTH(20) WIDTHTYPE(Remainder)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#CONNECT_SERVER_PANEL) DISPLAYPOSITION(9) HEIGHT(137) LEFT(300) PARENT(#TOP_PANEL) TABPOSITION(8) TABSTOP(False) TOP(8) WIDTH(213)
DEFINE_COM CLASS(#PRIM_PHBN) NAME(#CONNECT_SERVER) CAPTION('Connect to iSeries Server System') DISPLAYPOSITION(1) LEFT(16) PARENT(#CONNECT_SERVER_PANEL) TABPOSITION(1) TOP(32) WIDTH(172)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#CONNECT_MAIL_PANEL) DISPLAYPOSITION(8) HEIGHT(129) LEFT(300) PARENT(#TOP_PANEL) TABPOSITION(10) TABSTOP(False) TOP(16) VISIBLE(False) WIDTH(205)
DEFINE_COM CLASS(#PRIM_PHBN) NAME(#CONNECT_MAIL) CAPTION('Connect to Email System') DISPLAYPOSITION(1) LEFT(16) PARENT(#CONNECT_MAIL_PANEL) TABPOSITION(1) TOP(48) WIDTH(172)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#START_POLLING_PANEL) DISPLAYPOSITION(10) HEIGHT(129) LEFT(300) PARENT(#TOP_PANEL) TABPOSITION(9) TABSTOP(False) TOP(16) VISIBLE(False) WIDTH(205)
DEFINE_COM CLASS(#PRIM_PHBN) NAME(#START_POLLING) CAPTION('Start processing inbound emails') DISPLAYPOSITION(1) LEFT(16) PARENT(#START_POLLING_PANEL) TABPOSITION(1) TOP(66) WIDTH(172)
DEFINE_COM CLASS(#STD_NUM.Visual) NAME(#MAIL_POLLING_TIME) DISPLAYPOSITION(3) HEIGHT(19) LEFT(118) MARGINLEFT(0) PARENT(#START_POLLING_PANEL) TABPOSITION(3) TOP(95) WIDTH(37)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_8) CAPTION('seconds') DISPLAYPOSITION(2) HEIGHT(19) LEFT(158) PARENT(#START_POLLING_PANEL) TABPOSITION(2) TABSTOP(False) TOP(97) WIDTH(48)
DEFINE_COM CLASS(#PRIM_LABL) NAME(#LABL_9) CAPTION('Check for email every') DISPLAYPOSITION(4) HEIGHT(19) LEFT(8) PARENT(#START_POLLING_PANEL) TABPOSITION(4) TABSTOP(False) TOP(97) WIDTH(106)
* The AS/400 Server connection object
DEFINE_COM CLASS(#VL_SAM003) NAME(#SERVER)
* Email session and messages objects
DEFINE_COM CLASS(#S_208XSO.MAPISession) NAME(#MAIL_SESSION) reference(*Dynamic)
DEFINE_COM CLASS(#S_208XMO.MAPIMessages) NAME(#INBOUND_MAIL) reference(*Dynamic)
DEFINE_COM CLASS(#S_208XMO.MAPIMessages) NAME(#OUTBOUND_MAIL) reference(*Dynamic)
* The Email polling timer
DEFINE_COM CLASS(#PRIM_TIMR) NAME(#MAIL_POLLING_TIMER) INTERVAL(0)
* The MS-Word document handler
DEFINE_COM CLASS(#S_208RMW) NAME(#MS_WORD) DISPLAYPOSITION(2) PARENT(#COM_OWNER) TABPOSITION(2) VISIBLE(False)
* The MS-Excel document handler
DEFINE_COM CLASS(#S_208RME) NAME(#MS_EXCEL) PARENT(#COM_OWNER) VISIBLE(False)
* Lists used to store names and values extracted from MS-Word or MS-Excel documents
Def_list #List01 (#S_208Name #S_208Inst #S_208AVal #S_208NVal) Type(*Working) Entrys(100)
Def_list #List02 (#S_208Name #S_208Inst #S_208AVal #S_208NVal) Type(*Working) Entrys(100)
Def_list #List03 (#S_208Name #S_208Inst #S_208AVal #S_208NVal) Type(*Working) Entrys(100)
Def_list #List04 (#S_208Name #S_208Inst #S_208AVal #S_208NVal) Type(*Working) Entrys(100)
Def_list #List05 (#S_208Name #S_208Inst #S_208AVal #S_208NVal) Type(*Working) Entrys(100)
* List used to get messages back from the server
Define #MessCount Reffld(#ListCount)
Def_List Name(#MESSAGES) Fields(#S_208MSG) Counter(#MESSCOUNT) Type(*WORKING) Entrys(9999)
* Lists used to get spool file details back from the server
DEF_LIST NAME(#SPOOL01) FIELDS(#S_208MSG) TYPE(*WORKING) ENTRYS(240)
DEF_LIST NAME(#SPOOL02) FIELDS(#S_208MSG) TYPE(*WORKING) ENTRYS(240)
DEF_LIST NAME(#SPOOL03) FIELDS(#S_208MSG) TYPE(*WORKING) ENTRYS(240)
DEF_LIST NAME(#SPOOL04) FIELDS(#S_208MSG) TYPE(*WORKING) ENTRYS(240)
* Global flag to store the name of function to be called on the
* the server system to process a document has been found in the
* data extracted from a MS-Word or MS-Excel document
DEFINE_COM CLASS(#STD_OBJ) NAME(#RDML_FUNCTION)
* The event that signals that some documentation information has been found
* (also see S_208RMW and S_208RME that also signal this message)
Define_Evt InformationFound
Define_Map *input #S_208Name #WithName
Define_Map *input #S_208AVAL #WithValue
* ===============================
* Handle main form initialization
* ===============================
EVTROUTINE handling(#com_owner.Initialize)
* Set up the form caption and initalize other variables
SET #com_owner caption(*component_desc)
* Log the form start up to the event log
Invoke #Com_Owner.Log EventText(*component_desc) EventText2('started')
* Create and initialize the MAPI email session
Set_Ref #MAIL_SESSION (*Create_as #S_208XSO.MAPISession)
Set #MAIL_SESSION Parent(#Com_Owner)
Invoke #Mail_Session.Realize
* Create and initialize the MAPI email message handler for inbound mail
Set_Ref #INBOUND_MAIL (*Create_as #S_208XMO.MAPIMessages)
Set #Inbound_Mail Parent(#Com_Owner)
Invoke #Inbound_Mail.Realize
* Create and initialize the MAPI email message handler for outbound mail
Set_Ref #OUTBOUND_MAIL (*Create_as #S_208XMO.MAPIMessages)
Set #Outbound_Mail Parent(#Com_Owner)
Invoke #Outbound_Mail.Realize
ENDROUTINE
* ========================
* Handle main form closing
* ========================
EVTROUTINE handling(#com_owner.Closing)
* Disconnect the AS/400 server
Invoke #Server.uDisconnect
* Shutdown the MS-Word document handler
Invoke #MS_Word.Shutdown
* Shutdown the MS-Excel document handler
Invoke #MS_Excel.Shutdown
* Disconnect from the mail server
If '#Mail_Session.SessionId *ne 0'
Invoke #Mail_Session.SignOff
Endif
* Destroy all of the MAPI email objects
Invoke #OutBound_Mail.unRealize
Invoke #InBound_Mail.unRealize
Invoke #Mail_Session.unRealize
Set_Ref #OutBound_Mail *null
Set_Ref #InBound_Mail *null
Set_Ref #Mail_Session *null
ENDROUTINE
* ================================================
* Handle a request to connect to the AS/400 server
* ================================================
EVTROUTINE HANDLING(#CONNECT_SERVER.Click)
Invoke #Com_Owner.Log EventText('Connecting to iSeries server system')
INVOKE METHOD(#SERVER.uConnectModal)
ENDROUTINE
* =====================================================================
* Handle a server connection creation signalled by #SERVER (#VL_SAM003)
* =====================================================================
EVTROUTINE HANDLING(#SERVER.uConnectionCreated)
Invoke #Com_Owner.Log EventText('Now connected to iSeries server system')
* Make the connect to AS/400 server panel invisible
Set #Connect_Server_panel Visible(False)
* Now make the connect to email server panel visible
Set #Connect_Mail_panel Visible(True)
ENDROUTINE
* ===================================================
* Handle a request to connect to the to email system
* ===================================================
EVTROUTINE HANDLING(#CONNECT_Mail.Click)
* Logon / Connect to the email system
Invoke #Com_Owner.Log EventText('Signing on to email system')
Set #Mail_Session LogonUI(True)
Invoke #Mail_Session.Signon
* Link the mail inbound and outbound email sessions to the connection
Set #InBound_Mail SessionId(#Mail_Session.SessionId)
Set #OutBound_Mail SessionId(#Mail_Session.SessionId)
Invoke #Com_Owner.Log EventText('Signed on to email system')
* Make the connect to email server panel invisible
Set #Connect_Mail_panel Visible(False)
* Make the start processing email panel visible
* and set a default value for the polling time
Set #Start_Polling_panel Visible(True)
Set #Mail_Polling_Time Value(30)
ENDROUTINE
* ========================================================
* Check that the email pollng time specified is "sensible"
* ========================================================
EVTROUTINE HANDLING(#Mail_Polling_Time.LostFocus) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS)
Change #Std_Num #Mail_Polling_Time.Value
* If less then 10 set to 10, if greater than 600 set to 600
Case #Std_Num
When '< 10'
Set #Mail_Polling_Time Value(10)
When '> 600'
Set #Mail_Polling_Time Value(600)
EndCase
ENDROUTINE
* =============================================================
* Handle a request to start polling/checking for email messages
* =============================================================
EVTROUTINE HANDLING(#Start_Polling.Click)
* Make the start processing email panel invisible
Set #Start_Polling_Panel Visible(False)
* Make all the connection details and instructions at the top
* of the main form disappear
Set #Top_Panel Visible(False)
* Start the mail polling timer running (see #Mail_Polling_Timer.Tick)
Set #Mail_Polling_Timer Interval(1)
ENDROUTINE
* =================================================
* Handle a tick of the mail polling timer
* (ie: It's time to check for newly arrived email)
* =================================================
EVTROUTINE HANDLING(#Mail_Polling_Timer.Tick) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS)
Define #A_Limit Reffld(#Std_Num) Desc('Count of inbound emails')
Define #A_Index Reffld(#Std_Num) Desc('Loop index for inbound messages loop')
Define #MsgIndex Reffld(#Std_Num) Desc('Index to current inbound email')
* Stop the timer
Set #Mail_Polling_Timer Interval(0)
* Log a starting message
Invoke #Com_Owner.Log EventText('Checking for new emails')
* Fetch an updated email list from the Inbox
Invoke #InBound_Mail.Fetch
* Loop through all email messages currently in the InBox
Clr_List #Mail_List
Change #A_Limit #InBound_Mail.MsgCount
Begin_Loop from(1) to(#A_Limit) Using(#A_Index)
Change #MsgIndex '#A_Index - 1'
* Set the index to the current email message details
Set #InBound_Mail MsgIndex(#MsgIndex)
* Skip this message if it's already been read or if it has no attachments
Continue '(#InBound_Mail.MsgRead = True) or (#InBound_Mail.AttachmentCount <= 0)'
* Assemble the message details to place into the visible list
Change #SysVar$Av #InBound_Mail.MsgSubject
Change #Std_TextL #InBound_Mail.MsgOrigDisplayName
Change #Std_Desc #InBound_Mail.MsgDateReceived
* Add an entry to the mail list visible on the mail form
Add_Entry #Mail_List
* Loop around and process the next message
End_Loop
* Log a completion message
Invoke #Com_Owner.Log EventText('Finished checking for new emails')
* Update the display of the mail details on the main form so that they become immediately visible
Invoke #Mail_List_Group.UpdateDisplay
* Now do a second pass through the messages and pick out all unread
* messages that have attachments. These are eligible for processing
Invoke #Com_Owner.Log EventText('Now checking for unread emails with attachments')
Change #A_Limit #InBound_Mail.MsgCount
Begin_Loop from(#A_Limit) to(1) Using(#A_Index) Step(-1)
Change #MsgIndex '#A_Index - 1'
* Set the index to the current email message details
Set #InBound_Mail MsgIndex(#MsgIndex)
* Skip this message if it's already been read or if it has no attachments
Continue '(#InBound_Mail.MsgRead = True) or (#InBound_Mail.AttachmentCount <= 0)'
* We now have a message to be handled, invoke HandleAttachments to check out any attachments that this email may have
Invoke #Com_Owner.HandleAttachments
* Loop around and process the next email message
End_Loop
Invoke #Com_Owner.Log EventText('Finished checking for unread emails with attachments')
* Now restart the timer
Change #Std_Num '#Mail_Polling_Time.Value * 1000'
Set #Mail_Polling_Timer Interval(#Std_Num)
* Finished .... we'll now wait for the next tick of the timer and do it all again
ENDROUTINE
* ====================================================
* Handle all attachments in the current email message
* ====================================================
MthRoutine HandleAttachments
Define #B_Limit Reffld(#Std_Num) Desc('Loop Limit')
Define #B_Index Reffld(#Std_Num) Desc('Loop Index')
Define #AtchIndex Reffld(#Std_Num) Desc('Current Attachment Index')
Define #RetCode2 *char 2 Desc('Standard char(2) LANSA return code')
* Log start
Invoke #Com_Owner.Log EventText('Processing' ) EventText2(#InBound_Mail.MsgSubject) EventText3('from') EventText4(#InBound_Mail.MsgOrigDisplayName)
* Loop through all the attachments in the current email message
Change #B_Limit #InBound_Mail.AttachmentCount
Begin_Loop from(1) to(#B_Limit) Using(#B_Index)
Change #AtchIndex '#B_Index - 1'
Set #InBound_Mail AttachmentIndex(#AtchIndex)
* Invoke HandleDocument to handle a single document attached to the current email message
Invoke #Com_Owner.HandleDocument DocumentName(#InBound_Mail.AttachmentName) DocumentPathName(#InBound_Mail.AttachmentPathName)
End_Loop
* Log end
Invoke #Com_Owner.Log EventText('Finished processing' ) EventText2(#InBound_Mail.MsgSubject) EventText3('from') EventText4(#InBound_Mail.MsgOrigDisplayName)
Endroutine
* ===============================================================
* Handle a single attached document in the current email message
* ===============================================================
MthRoutine HandleDocument
Define_Map *input #SysVar$Av #DocumentName
Define_Map *input #SysVar$Av #DocumentPathName
Define #Position Type(*Dec) Length(3) decimals(0) Desc('Scan Position')
Define #Temp_File Reffld(#SysVar$av) Desc('Temporary File Name')
Def_Cond *Found '#Position > 0'
* Log attachment processing start
Invoke #Com_Owner.Log EventText('Processing attachment' ) EventText2(#DocumentName.Value) EventText3('in') EventText4(#DocumentPathName.Value)
* Clear all the storage areas and lists used betwene the client (this component)
* and the server (RDML function SET208H).
* List01 -> List05 are the values extracted from the MS-Word or MS-Excel document
Change #ListCount 0
Clr_List #List01
Clr_List #List02
Clr_List #List03
Clr_List #List04
Clr_List #List05
* Messages is the list of messages returned by the AS/400 server after
* the document has been processed. Ultimately Messages is used to form the
* text of the attachment file that is sent back to the email sender.
Clr_List #Messages
* Spool01 -> Spool04 are any spool file details that have been sent back
* by the AS/400 server. These are added to the Messages list and also
* sent back to the email sender. See RDML function SET208Q for an example
* of a function that prints a report on the server and sends the spool file
* details back in lists Spool01 -> Spool04
Clr_List #Spool01
Clr_List #Spool02
Clr_List #Spool03
Clr_List #Spool04
* Set the name of the RDML function to be called to handle this document
* to blanks to indicate that it has not been found in the document data (yet).
Set #RDML_FUNCTION Value(*Blanks)
* Now see if this attachment is a MS-Word document
Use ScanString (#DocumentName.Value '.DOC' 1 '1' '1') To_Get(#Position)
* If it is a MS-Word document invoke #MS_Word.ExtractInformation to extract all the
* book mark details from the document. The details are signalled back to this
* component by "InformationFound" events issued by #MS_Word.ExtractInformation.
If *Found
Invoke #Com_Owner.Log EventText('Found MS-Word document' ) EventText2(#DocumentName.Value)
Invoke #MS_Word.ExtractInformation FromDocument(#DocumentPathName.Value)
Else
* If not a MS-Word document, see if this attachment is a MS-Excel document
Use ScanString (#DocumentName.Value '.XLS' 1 '1' '1') To_Get(#Position)
* If it is a MS-Word document invoke #MS_Excel.ExtractInformation to extract all the
* speadsheet cell details from the document. The details are signalled back to this
* component by "InformationFound" events issued by #MS_Excel.ExtractInformation.
If *Found
Invoke #Com_Owner.Log EventText('Found MS-Excel document' ) EventText2(#DocumentName.Value)
Invoke #MS_Excel.ExtractInformation FromDocument(#DocumentPathName.Value)
Endif
Endif
* If something was added to one of the lists by one of the information
* extractors (ie: #MS_Word.ExtractInformation or #MS_Excel.ExtractInformation)
* we need to place a call to the AS/400 server application to process the
* extracted details ....
If '#ListCount > 0'
* If the name of the RDML function to be used on the server to process
* the information extracted from the document has not been found in
* the document set a default value from the first 7 characters of the
* attachment file name .....
If '#RDML_Function.Value = *Blanks'
Define #TmpChar07 *char 7
Change #TmpChar07 #DocumentName.Value
Signal InformationFound WithName(RDML_FUNCTION) WithValue(#TmpChar07)
Endif
* Log an event identifying the RDML function that will used to handle the document on the server system
Invoke #Com_Owner.Log EventText('RDML function' ) EventText2(#RDML_Function.Value) EventText3('will be used to handle document') EventText4(#DocumentName.Value)
* Do the call to the remote procedure. Call RDML function SET208H which will manage details of calling the handling RDML function specified in #RDML_Function.Value
USE CALL_SERVER_FUNCTION WITH_ARGS(*SSERVER_SSN SET208H N Y #LIST01 #LIST02 #LIST03 #LIST04 #LIST05 #Messages #Spool01 #Spool02 #Spool03 #Spool04) TO_GET(#RetCode2)
* If the call to RDML function SET208H failed, log an error into the event log
If '#RetCode2 *ne OK'
Invoke #Com_Owner.Log EventText('***ERROR*** Call to server message handler failed.' )
Endif
* Now collect any messages on the current message queue and add them to the message list and then clear the message queue
Use Get_Message To_Get(#RetCode2 #S_208Msg)
Dowhile '(#MessCount < 9999) and (#RetCode2 = OK)'
Add_Entry #Messages
Use Get_Message To_Get(#RetCode2 #S_208Msg)
EndWhile
Use Clr_Messages
* Now collect any returned spool file lines and place them into the message list as well
SelectList #Spool01
Add_Entry #Messages
EndSelect
SelectList #Spool02
Add_Entry #Messages
EndSelect
SelectList #Spool03
Add_Entry #Messages
EndSelect
SelectList #Spool04
Add_Entry #Messages
EndSelect
* Now transform the entire messages list into a temporary flat file (name is in #Temp_File)
Use tConcat (*Temp_Dir 'S_208FMF_Reply.txt') (#Temp_File)
USE BUILTIN(TRANSFORM_LIST) WITH_ARGS(#Messages #Temp_File C B T) TO_GET(#RetCode2)
* If the TRANSFORM_LIST operation failed, log an error to the event
* log and blank out the temporary file name so that it will not be
* sent as an attachment later
If '#RetCode2 *ne OK'
Invoke #Com_Owner.Log EventText('***ERROR*** Attempt to save temporary file failed.' )
Change #Temp_File *Blanks
Endif
* Now assemble the reply email
Invoke #OutBound_Mail.Compose
* Set up the addressing details
Set #OutBound_Mail RecipDisplayName(#InBound_Mail.MsgOrigDisplayName)
Set #OutBound_Mail RecipAddress(#InBound_Mail.MsgOrigAddress)
Set #OutBound_Mail AddressResolveUI(False)
* Set up the subject
Use bConcat ('Automatic Response to ->' #InBound_Mail.MsgSubject) (#SysVar$av)
Set #OutBound_Mail MsgSubJect(#SysVar$av)
* Set up the message text body
Set #OutBound_Mail MsgNoteText('Please read the attachment for response details.')
* Add the temporary messages file (if it was saved okay) to the
* email as an attachment
If '#Temp_File *ne *Blanks'
Set #OutBound_Mail AttachmentPathName(#Temp_File)
Endif
* Log an event indicating that email is about to be sent
Invoke #Com_Owner.Log EventText('Sending reply email to' ) EventText2(#OutBound_Mail.RecipDisplayName)
* Send the email message back to the original sender
Invoke #OutBound_Mail.Send vDialog(0)
Endif
* Log document processing end
Invoke #Com_Owner.Log EventText('Finished processing attachment' ) EventText2(#DocumentName.Value) EventText3('in') EventText4(#DocumentPathName.Value)
Endroutine
* ========================================================================
* Handle extracted information coming back from this component itself, the
* MS-Word information extractor or the MS-Excel information extractor
* ========================================================================
EVTROUTINE HANDLING(#COM_Owner.InformationFound #MS_Word.InformationFound #MS_Excel.InformationFound) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS) WithName(#WithName) WithValue(#WithValue)
Define #Pos *Dec 3 0
Define #Int *Dec 15 0
Define #Dec *Dec 9 9
Define #LastPos Reffld(#pos)
Define #TWithName Reffld(#S_208Name)
Define #RetCode *char 1
* Set up the default values for the entry to be stored in the lists
* that will be eventually passed to the server function SET208H
* #S_208NAME - the NAME (most commonly a MS-Word bookmark or CELL_rrrrrrr_ccccccc)
Change #S_208Name #WithName.value
Use UpperCase (#S_208Name) (#S_208Name)
* #S_208INST - the INSTANCE of the name
Change #S_208Inst 1
* #S_208AVAL - the ALPHANUMERIC value
Change #S_208AVal #WithValue.value
* #S_208NVAL - the NUMERIC value (if a conversion is possible)
Change (#Int #Dec) *Null
Use CHECKNUMERIC WITH_ARGS(#S_208AVal 15 9) TO_GET(#Int #Dec #RetCode)
Change #S_208NVal '#Int + #Dec'
* Now see if the name ends in an instance number (ie: the name is in
* the format NAME_nnnn) and if it does, extract the instance number
* and remove the instance number from the name. Thus the name
* EMPNO_56 changes #S208Inst to 56 and #S_208Name to EMPNO.
* Likewise the the name CELL_000007_00005 would be reduced
* to name CELL_000007 and instance number 5
Change #Pos 1
Change #LastPos 0
Begin_Loop
Use ScanString WITH_ARGS(#S_208Name '_' #Pos) TO_GET(#Pos)
Leave '#Pos <= 0'
Leave '#Pos >= 32'
Change #LastPos #Pos
Change #Pos '#Pos + 1'
End_Loop
If '#LastPos > 0'
Change #TWithName *Blanks
Substring (#S_208Name #LastPos) (#TWithName)
Change #Int *Null
Use CHECKNUMERIC WITH_ARGS(#TWithName 7 0 '_') TO_GET(#Int #Dec #RetCode)
If '(#RetCode = Y) and (#Int > 0)'
Change #S_208Inst #Int
Substring (#Blank) (#S_208Name #LastPos *End)
Endif
Endif
* We now should have the #S208Name, #S208Inst, #S_208Aval and #S_208NVal
* values finalized ... so add an entry to appropriate storage list.
*
* Five lists (List01 -> List05) are used here to avoid any one list being
* more than 32,000 bytes long when it is passed to the server function
* SET208H. Logically they can be thought of as a single list.
Case #ListCount
When '< 100'
Add_Entry #List01
When '< 200'
Add_Entry #List02
When '< 300'
Add_Entry #List03
When '< 400'
Add_Entry #List04
When '< 500'
Add_Entry #List05
Otherwise
Invoke #Com_Owner.Log EventText('***ERROR*** List overflow. Data ignored.') EventText2(#S_208AVal)
EndCase
* Keep a count of the total number of list entries added
Change #ListCount '#ListCount + 1'
* If the name just processed is "RDML_FUNCTION" then save the
* value. This name is used by method routine "HandleDocument" to
* decide whether it should add a default function name to the
* list of document values.
If '#S_208Name = RDML_FUNCTION'
Set #RDML_FUNCTION Value(#S_208AVal)
Endif
Endroutine
* =====================================
* Log an Event to the visible event log
* =====================================
MthRoutine Log
Define_Map *input #SysVar$Av #EventText
Define_Map *input #SysVar$Av #EventText2 Mandatory(' ')
Define_Map *input #SysVar$Av #EventText3 Mandatory(' ')
Define_Map *input #SysVar$Av #EventText4 Mandatory(' ')
* Clear the log if it has more than 200 message in it
If '#Event_Log.Entries > 200'
Clr_List #Event_Log
Endif
* Concatenate the message parts together
Use bConcat (#EventText.Value #EventText2.Value #EventText3.Value #EventText4.Value) (#SysVar$Av)
* Set the time and add an entry to the event log
Change #Time *Time
Add_Entry #Event_Log
Set #Event_Log.CurrentItem EnsureVisible(True)
* Update the display so that the event log message appears instantly
Invoke #Event_Log_Group.UpdateDisplay
Endroutine
END_COM