Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to Set up the Default Email Account in Outlook Programmatically in VFP Send Mail

Status
Not open for further replies.

carolx

Programmer
Jul 22, 2003
75
JM

I got the following code from Marcia Akins et al cntMapi class which I modified to send PDF document by email. The client uses Outlook and would like to change the Default Email Account in the FoxPro code without employee intervention and back to the original at the end of processing.

I want to know, also, if I change the Email Client to Mail if the output will be sent to Mail Outbox, and if this can done programmatically.

Send Routine

* This class is for Consoft payroll only/see text file version code in turbopay8 folder --> sendmail.prg
* Email .pdf file

LOCAL lcBDPE, lcAttachment, lcCurDir, lnSessionID, lnFile, lnCnt, lnPos, myvar, pcycle, lcPath ,llError,lcDcode,;
lcSec,lcMessage,lnLen,lcOldError,lcObj,lcCentury,laMail[1]
SET STEP ON
lcCurDir = FULLPATH( CURDIR() )
lcPath = SET("PATH")
SET PATH TO &lcCurDir
lcCentury = SET("Century")
SET CENTURY ON
lcPayslipfile = ''

*** Make sure we have a MAPI session established

IF !EMPTY(pycntrl.mailclient)
oSendparms.cUsername = TRIM(pycntrl.mailclient)
ELSE
oSendparms.cUsername = ""
ENDIF
oSendparms.cPassword = ""
oSendparms.lDownload = .F.

DO CASE
CASE UPPER(pycntrl.cycle) = "W"
pcycle = "week"
CASE UPPER(pycntrl.cycle) = "F"
pcycle = "fortnight"
CASE UPPER(pycntrl.cycle) = "B"
pcycle = "bi-monthly cycle"
CASE UPPER(pycntrl.cycle) = "M"
pcycle = "month"
ENDCASE

lnSessionID = THIS.CreateSession( oSendparms.cUserName, oSendparms.cPassWord, oSendparms.lDownload )

IF lnSessionID > 0
*** Create message and send it
WITH THIS.oMessage
.SessionID = lnSessionID
SET PRINTER TO NAME 'BULLZIP PDF PRINTER'
WAIT 'Salary deduction notifications are being mailed.' WINDOW NOWAIT NOCLEAR

SELECT driver
SCAN
lcDcode = code
lcAttachment = ''
*----------------------------------------------------------------------------------------------NEW CODE

lcMessage = 'An error occurred when sending deduction notification.'+CHR(13)+;
'An attempt to reset the default PDF file failed'+CHR(13)+;
'Please close the PDF file if is in opened'+CHR(13)+;
'The program will terminate.'

lcOldError = ON("ERROR")
ON ERROR llError = .T.
IF ADIR(laMail,lcPayslipfile) = 1
ERASE (lcPayslipfile)
IF llError = .T.
=MESSAGEBOX(lcMessage, 16, 'Salary Deduction Notification' )
CANCEL
ENDIF
ENDIF
llError = .F.
ON ERROR &lcOldError

lcPayslipfile = Textmerge('c:\email\DeductionNotification<<TRIM(driver.code)+DTOC(pycntrl.perdt,1)>>.pdf')

* Create the COM object to control the printer.
lcObj = CreateObject("BullZIP.PDFPrinterSettings")
lcObj.SetValue("Output",lcPayslipfile)
* lcObj.SetValue("WatermarkText" ,"Draft")
* lcObj.SetValue("WatermarkColor","#FF9900")
lcObj.SetValue("ShowSettings" ,"never")
lcObj.SetValue("ShowPDF" ,"no")
lcObj.WriteSettings(.t.)

IF !EMPTY(glAll)
SELECT d.empno,namel,namef,name AS institution,desc AS deduction,d.code,per,p.email FROM pyemdedw d ;
JOIN pyemplw m ON d.empno = m.empno ;
JOIN pydedn p ON d.code = p.code ;
WHERE per > 0 AND !EMPTY(p.email);
AND d.code = lcDcode;
ORDER BY namel,namef,deduction;
INTO CURSOR dedmail
ENDIF

IF !EMPTY(gcDcode)
SELECT d.empno,namel,namef,name AS institution,desc AS deduction,d.code,per,p.email FROM pyemdedw d ;
JOIN pyemplw m ON d.empno = m.empno ;
JOIN pydedn p ON d.code = p.code ;
WHERE per > 0 AND !EMPTY(p.email);
AND d.code = gcDcode;
ORDER BY namel,namef,deduction;
INTO CURSOR dedmail
ENDIF

* oGv.pcReportTitle = dedmail.deduction
REPORT FORM institutiondeductions NOCONSOLE TO PRINTER

lcMessage = 'The creation of the attachment is taking too long.'+CHR(13)+;
'Ask your administrator to reset the name of the PDF file'+CHR(13)+;
'in the Bullzip utility interface to c:\email\payslip.pdf'+CHR(13)+;
'if it was changed. The program will terminate.'

lcSec = SECONDS()
*DECLARE Sleep IN kernel32 INTEGER dwMilliseconds
DO WHILE NOT ADIR(laMail,lcPayslipfile) = 1
*Sleep(5000)
IF SECONDS() - lcSec > 35
=MESSAGEBOX(lcMessage, 16, 'Salary Deduction Notification')
CANCEL
ENDIF
ENDDO

*----------------------------------------------------------------------------------------------

lcMessage = 'The attachment ID does not match the institution being processed.'+CHR(13)+;
'The program will terminate.'

lnLen = LEN(lcPayslipfile) - 4
*IF UPPER(SUBSTR(lcPayslipfile,22,lnLen - 21 - 8)) == UPPER(TRIM(driver.empno))
lcAttachment = (lcPayslipfile)
*ELSE
* =MESSAGEBOX(lcMessage, 16, 'Non-Statutory Deductions Notification')
* CANCEL
*ENDIF

oSendparms.aRecipients(1,1) = ALLTRIM(driver.email)
oSendparms.aRecipients(1,2) = 1
oSendparms.aAttachments(1) = lcAttachment
oSendparms.cSubject = "Salary Deductions Notification for "+ALLTRIM(driver.name)

myvar = " "
SET TEXTMERGE ON NOSHOW
SET TEXTMERGE TO MEMVAR myVar

\TO: <<TRIM(driver.name)>>
\Attached is the salary deduction listing showing payments made for <<pcycle>> ending <<pycntrl.perdt>>.
\FROM: <<pycntrl.name>>

SET TEXTMERGE TO
SET TEXTMERGE OFF

oSendparms.cBodytext = myvar

.Compose()
*** Make sure we have enough room to add the attachments on to the end of the body
.MsgNoteText = oSendparms.cBodyText + CHR(13) + CHR(13) + ;
SPACE( ALEN( oSendparms.aAttachments, 1 ) + 2 )
.MsgSubject = oSendparms.cSubject

*** Add the recipients
*** The e-mail address is column 1
*** The recipient type is column 2
FOR lnCnt = 1 TO ALEN( oSendparms.aRecipients, 1 )
.RecipIndex = .RecipCount
.RecipDisplayName = ALLTRIM( oSendparms.aRecipients[ lnCnt, 1 ] )
.RecipType = oSendparms.aRecipients[ lnCnt, 2 ]
ENDFOR

*** Finally add the attachments
*** find the correct position for the first one
lnPos = LEN( oSendparms.cBodyText ) + 3
IF NOT EMPTY( oSendparms.aAttachments[ 1 ] )
FOR lnCnt = 1 TO ALEN( oSendparms.aAttachments, 1 )
.AttachmentIndex = .AttachmentCount
.AttachmentPosition = lnPos
.AttachmentName = JUSTFNAME( ALLTRIM( oSendparms.aAttachments[ lnCnt ] ) )
.AttachmentPathName = ALLTRIM( oSendparms.aAttachments[ lnCnt ] )
lnPos = lnPos + 1
ENDFOR
ENDIF

*** All systems go: send the e-mail
*** An argument of 1 will open client to manually send composed message

.Send(0)

ENDSCAN
ENDWITH

*** Sign off
IF ADIR(laMail,lcPayslipfile) = 1
ERASE (lcPayslipfile)
ENDIF

SET PRINTER TO DEFAULT
WAIT CLEAR
This.oSession.SignOff()
ELSE
SET DEFAULT TO ( lcCurDir ) && Default directory
SET PATH TO &lcPath
SET CENTURY &lcCentury
MESSAGEBOX( 'Unable to create MAPI Session', 16, 'Major WAAAHHH!' )
RETURN .F.
ENDIF
SET DEFAULT TO ( lcCurDir ) && Default directory
SET PATH TO &lcPath
SET CENTURY &lcCentury


 
Sorry, all that code youre posting here does not reveal essential information about what you're actually using here.

pycntrl.mailclient "falls from the sky", by which I mean nowhere before a table named pycntrl is mentioned and its structure and data, I can only assume this is a table, might also be an object. And that's not the only place of code using something that's not introduced beforehand.

I think you wanted to concentrate on the major code already, but it's not helpful to show how you produce a PDF with Bullzip when finally the question is about mailing.

So let me just answer very general level:

MAPI is Microsofts mail API addressing the default MAPI mail client in a system. So addressing several clients you know exists on the system via MAPI would mean to change the default MAPI client. I don't know, I think that's possible just like it's possible to change the default printer. In printing, VFP has a much simpler and less intrusive way to just change its default printer without making it the system default printer. There's no such simple setting similar to SET PRINTER like SET MAIL, but as you also find Windows API to change the system default printer forth and back, if it's really necessary, I'm confident you find something that changes the default mail client.

On the system settings, the default mail client is defined in standard apps. I find an entry point to the topic here:
I don't know, I wouldn't go the route of defining a mail account for your special mailings in Windows Mail. Isn't it much easier to set up more accounts in Outlook and make use of them?

I do have several mail accounts in my Outlook and it's easy to send from them via this:

Code:
#Define olMailItem 0
Local loOL As Outlook.Application, loAccount as Outlook.Account,  loMail As Outlook.MailItem

loOL = Createobject("outlook.application")
loMail = loOL.CreateItem(olMailItem)
[highlight #FCE94F]loMail.SendUsingAccount = loOL.Session.Accounts.Item("<<AccountName>>")[/highlight]

loMail.To = 'someone@example.com'
loMail.Body = 'This is a test'
loMail.Subject ='Testmail 1'

loMail.Display()

For example, I simply named my outlook accounts by mail addresses (as it's also usual) and so <<AccountName>> would simply be the mail account you want to set as FROM address. That can also mean an alias for the same mail address with just it's own Outlook account pst file and outbox, etc.

If it's only about eventually putting the sent item into a specific outlook folder, there's more about outlook OLE automation of items, not only mail item, to move them between Outlook folders.

Overall I don't see the need to switch to Windows Mail. If you really not want mail items to get into any outbox use directer mailing via an SMTP solution. Watch out what you can do, the moist a recent thread thread184-1798432 shows older code here or in Fox Wikis may not work out, I'd recommend using blat.dll, but also watch out for legal issues, for example about your legal storage obligations of business communication at least about business documents like invoices.

If you really want to do this on a professional level mass mailings of business documents, for example, emails associated with an online shop about order confirmation, information about sending (partial) orders, etc., then go about an Exchange solution, not Outlook. Automating Exchange will usually be done on a dedicated server, not any client. I have no experience with this, but you find that mentioned on StackExchange a lot. Not VFP, but VBA automation is transcribable.

Bye, Olaf.

Olaf Doschke Software Engineering
 
I sent the send mail portion of the code to give an overall picture of what was being done.

I found a solution I think. Create a new Profile and set up the (default) email account only in that profile. In ControlPanel --> Mail select the option 'Prompt for a Profile to be used' Whenever Outlook is opened it prompts for a profile selection. Select the new profile.

Thanks Olaf
 
You're welcome, Carol.

I don't know why you think it's necessary to make such a setup after I showed you how to set the SendUsingAccount property, there is no user interaction necessary and the additional account doesn't need to become the default, not even temporary.

Regarding your code posting, well, it's both more than just the code sending mail, and also less at the same time. The essential mail composition and sending code is between .Compose() and .Send(0) and since these begin with points that's only possible if this code is within some WITH..ENDWITH section and that also means you do a lot of things in this section that's not directöy email-related. One can guess you use CDO.Message, which complicates things when you could simply use Outlook automation as I showed.

Anyway, problem solved, I guess.

Bye, Olaf.


Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top