The following code explains how to open the file attachment which is stored as blob data in database.
Parameter: emailItemId which is used to identify the attachment saved in SysOutgoingEmailData table.
This method can be called from a button click in the "Email-sending status" from from Admin-> Periodic->Email processing
void ShowAttachment(SysEmailItemId _emailItemId)
{
SysOutgoingEmailData outgoingEmailData;
str tempPath;
BinData binData;
FileIOPermission fileIOPermission;
str filePathName;
int retVal;
;
fileIOPermission = new FileIOPermission('','r');
fileIOPermission.assert();
//BP Deviation Documented
//tempPath = WinApiServer::getTempPath();
tempPath = WinApi::getTempPath();
CodeAccessPermission::revertAssert();
// add embedded objects and attachments to the message
select outgoingEmailData
index hint EmailDataIdx
where outgoingEmailData.EmailItemId == _emailItemId; //OutgoingEmail.EmailItemId;
if (SysEmailDistributor::validateFileName(outgoingEmailData.FileName))
{
binData = new BinData();
binData.setData(outgoingEmailData.Data);
if (outgoingEmailData.EmailDataType == SysEmailDataType::Embedded)
// embedded images are renamed to ensure uniqueness
filePathName = tempPath + int642str(outgoingEmailData.EmailItemId) + '_' + int2str(outgoingEmailData.DataId);
else
// attachment cannot be renamed
filePathName = tempPath + outgoingEmailData.FileName;
if (outgoingEmailData.FileExtension)
filePathName = filePathName + outgoingEmailData.FileExtension;
fileIOPermission = new FileIOPermission(filePathName,'w');
fileIOPermission.assert();
//BP Deviation Documented
binData.saveFile(filePathName);
CodeAccessPermission::revertAssert();
if (outgoingEmailData.FileExtension == ".htm")
retVal = WinApi::shellExecute(filePathName,"","","",1,false);
else
{
retVal = WinApi::shellExecute(filePathName,"","","",1,true);
fileIOPermission = new FileIOPermission(filePathName,'w');
fileIOPermission.assert();
//BP Deviation Documented
WinApi::deleteFile(filePathName);
CodeAccessPermission::revertAssert();
}
}
}
Thursday, January 21, 2010
Wednesday, January 20, 2010
Lookup using temporary tables
Create lookup using temporary table. Populate the temporary table with the required data from different table or if a particular values should be shown first. In the below example, the Tmpcontactperson table can populated with required data and the lookup called using the code below.
public void lookup()
{
Tmpcontactperson tmpContactPerson;
//insert record into temporary table for different criteria and perform lookup
sysTableLookup = SysTableLookup::newParameters(tableNum(Tmpcontactperson),this,false );
sysTableLookup.addLookupField(fieldNum(Tmpcontactperson, ContactPersonId),True); sysTableLookup.addLookupField(fieldNum(Tmpcontactperson, CustAccount),false);
sysTableLookup.addLookupField(fieldNum(Tmpcontactperson, Name),False);
sysTableLookup.addLookupField(fieldNum(Tmpcontactperson, Email),False);
sysTableLookup.addLookupField(fieldNum(Tmpcontactperson, Function),false);
sysTableLookup.parmTmpBuffer(tmpContactPerson);
sysTableLookup.performFormLookup();
}
public void lookup()
{
Tmpcontactperson tmpContactPerson;
//insert record into temporary table for different criteria and perform lookup
sysTableLookup = SysTableLookup::newParameters(tableNum(Tmpcontactperson),this,false );
sysTableLookup.addLookupField(fieldNum(Tmpcontactperson, ContactPersonId),True); sysTableLookup.addLookupField(fieldNum(Tmpcontactperson, CustAccount),false);
sysTableLookup.addLookupField(fieldNum(Tmpcontactperson, Name),False);
sysTableLookup.addLookupField(fieldNum(Tmpcontactperson, Email),False);
sysTableLookup.addLookupField(fieldNum(Tmpcontactperson, Function),false);
sysTableLookup.parmTmpBuffer(tmpContactPerson);
sysTableLookup.performFormLookup();
}
Thursday, January 7, 2010
SO confirmation: Add email with pdf attachment to batch processing
Requirement:
{
salesTable salesTablelocal
container conSysEmail;
boolean ok = true;
salesTablelocal = salesTable::find(custConfirmJour.SalesId);
//container: parameters 1 -> to identify if called from sales
// parameter 2 -> to get the sales email id
conSysEmail = conins(conSysEmail,1,NoYes::Yes,salesTablelocal.Email);
//set the container value in the info class. A new get/set method to store the container.
infolog.parmSOPOConfirmEmail(conSysEmail);
}
public void printJournal()
{
if (journalList.len() > 0)
{
if (printFormletter)
{
this.setConfirmEmailId();
custConfirmJour.printJournal(this, journalList);
}
if (salesParmUpdate.Proforma)
this.removeProforma();
}
}
In the Info class add the following code to reportSendMail() method to send mail using batch for pdf instead of outlook client.
void reportSendMail(PrintJobSettings p1)
{
boolean pdfFormat;
Map mappings;
SysEmailParameters emailParams;
Filename filePath;
Filename filenamelocal;
Filename fileExtension;
FilenameOpen attachmentFilename;
str attachmentsFolder;
SysEmailId emailId;
SysEmailTable table;
LanguageId languageId;
NoYes callerSales;
int i;
SysINetMail m = new SysINetMail();
str fileName = 'axaptareport';
;
if (p1.format() == PrintFormat::ASCII p1.format() == PrintFormat::TEXTUTF8)
fileName = fileName + '.txt';
else if (p1.format() == PrintFormat::RTF)
fileName = fileName + '.rtf';
else if (p1.format() == PrintFormat::HTML)
fileName = fileName + '.htm';
else if (p1.format() == PrintFormat::PDF p1.format() == PrintFormat::PDF_EMBED_FONTS)
{
fileName = fileName + '.pdf';
pdfFormat = true;
}
//check if this is called from SO confirmation
//conSysEmail = infolog.parmSOPOConfirmEmail();
if (conlen(conSysEmail)>1 && pdfFormat)
{
//The file name will be in the local client temp folder.
attachmentFilename = p1.fileName();
[filePath, filenamelocal, fileExtension] = Global::fileNameSplit(attachmentFilename);
attachmentsFolder = Global::strReplace(emailParams.AttachmentsPath,'//','/');
if (substr(attachmentsFolder, strlen(attachmentsFolder), 1) != '\\')
attachmentsFolder = attachmentsFolder + "\\";
if (attachmentsFolder)
{
//Copy the file to the server folder which should be shared and should
//be on the network. This folder should be setup in the Email parameters.
attachmentsFolder = attachmentsFolder + filenamelocal + ".pdf";
info::copyFile(attachmentFilename,attachmentsFolder);
callerSales = conpeek(conSysEmail,1);
if (callerSales == NoYes::Yes)
emailId = CustFormletterParameters::find().CAP_ConfirmationEmailTemplate;
else
emailId = VendFormletterParameters::find().CAP_ConfirmationEmailTemplate;
table = SysEmailTable::find(emailId);
if (table)
{
languageId = table.DefaultLanguage;
mappings = new Map(Types::String, Types::String);
//mappings.insert("SubscriptionId","S001");
for (i = 2; i <= conlen(conSysEmail); i = i + 2)
SysEmailTable::sendMail(table.EmailId,languageId,conpeek(conSysEmail,i),mappings,attachmentsFolder,"",true,curuserid());
}
else
infolog.add(Exception::Error,"Email template parameter not available");
}
else
infolog.add(Exception::Error,"Attachment folder for sending email is not setup in the parameters");
}
else
m.sendMailAttach(p1.mailTo(),p1.mailCc(), p1.mailSubject(),'axapta report', true, p1.fileName(), fileName);
}
---------------------------
container CAP_parmSOPOConfirmEmail(container _conSysEmail = conSysEmail)
{
conSysEmail = _conSysEmail;
return conSysEmail;
}
---------------------------
server static void copyFile(FilenameOpen _attachmentFilename,
str _attachmentsFolder)
{
Set permissionSet;
;
// Revert permissions
CodeAccessPermission::revertAssert();
permissionSet = new Set(Types::Class);
permissionSet.add(new FileIoPermission(_attachmentFilename,'r'));
permissionSet.add(new FileIoPermission(_attachmentsFolder,'w'));
CodeAccessPermission::assertMultiple(permissionSet);
// Move to processed folder
// BP Deviation Documented
winAPI::copyFile(_attachmentFilename,_attachmentsFolder,true);
CodeAccessPermission::revertAssert();
}
---------------------------
- During sales order confirmation, if the print management settings is email and format is PDF, the system uses the client outlook to send the PDF as mail attachment. Instead, it is required to add this PDF file to the Email batch process (similar to the alerts) in SysOutgoingEmailTable & SysOutgoingEmailData tables so that when the Batch processing is performed, the email will be sent. The email template will be setup in parameters and the email id should be picked from SO.
- A new E-mail template shall be created according to standard functionality. This template is then set as a new parameter the form “CustFormletterParameters” named “E-mail template”.
Solution:
In the class SalesFormLetter_Confirmation, create a new method setConfirmEmailId() and call this in printJournal()
void setConfirmEmailId(){
salesTable salesTablelocal
container conSysEmail;
boolean ok = true;
salesTablelocal = salesTable::find(custConfirmJour.SalesId);
//container: parameters 1 -> to identify if called from sales
// parameter 2 -> to get the sales email id
conSysEmail = conins(conSysEmail,1,NoYes::Yes,salesTablelocal.Email);
//set the container value in the info class. A new get/set method to store the container.
infolog.parmSOPOConfirmEmail(conSysEmail);
}
public void printJournal()
{
if (journalList.len() > 0)
{
if (printFormletter)
{
this.setConfirmEmailId();
custConfirmJour.printJournal(this, journalList);
}
if (salesParmUpdate.Proforma)
this.removeProforma();
}
}
In the Info class add the following code to reportSendMail() method to send mail using batch for pdf instead of outlook client.
void reportSendMail(PrintJobSettings p1)
{
boolean pdfFormat;
Map mappings;
SysEmailParameters emailParams;
Filename filePath;
Filename filenamelocal;
Filename fileExtension;
FilenameOpen attachmentFilename;
str attachmentsFolder;
SysEmailId emailId;
SysEmailTable table;
LanguageId languageId;
NoYes callerSales;
int i;
SysINetMail m = new SysINetMail();
str fileName = 'axaptareport';
;
if (p1.format() == PrintFormat::ASCII p1.format() == PrintFormat::TEXTUTF8)
fileName = fileName + '.txt';
else if (p1.format() == PrintFormat::RTF)
fileName = fileName + '.rtf';
else if (p1.format() == PrintFormat::HTML)
fileName = fileName + '.htm';
else if (p1.format() == PrintFormat::PDF p1.format() == PrintFormat::PDF_EMBED_FONTS)
{
fileName = fileName + '.pdf';
pdfFormat = true;
}
//check if this is called from SO confirmation
//conSysEmail = infolog.parmSOPOConfirmEmail();
if (conlen(conSysEmail)>1 && pdfFormat)
{
//The file name will be in the local client temp folder.
attachmentFilename = p1.fileName();
[filePath, filenamelocal, fileExtension] = Global::fileNameSplit(attachmentFilename);
attachmentsFolder = Global::strReplace(emailParams.AttachmentsPath,'//','/');
if (substr(attachmentsFolder, strlen(attachmentsFolder), 1) != '\\')
attachmentsFolder = attachmentsFolder + "\\";
if (attachmentsFolder)
{
//Copy the file to the server folder which should be shared and should
//be on the network. This folder should be setup in the Email parameters.
attachmentsFolder = attachmentsFolder + filenamelocal + ".pdf";
info::copyFile(attachmentFilename,attachmentsFolder);
callerSales = conpeek(conSysEmail,1);
if (callerSales == NoYes::Yes)
emailId = CustFormletterParameters::find().CAP_ConfirmationEmailTemplate;
else
emailId = VendFormletterParameters::find().CAP_ConfirmationEmailTemplate;
table = SysEmailTable::find(emailId);
if (table)
{
languageId = table.DefaultLanguage;
mappings = new Map(Types::String, Types::String);
//mappings.insert("SubscriptionId","S001");
for (i = 2; i <= conlen(conSysEmail); i = i + 2)
SysEmailTable::sendMail(table.EmailId,languageId,conpeek(conSysEmail,i),mappings,attachmentsFolder,"",true,curuserid());
}
else
infolog.add(Exception::Error,"Email template parameter not available");
}
else
infolog.add(Exception::Error,"Attachment folder for sending email is not setup in the parameters");
}
else
m.sendMailAttach(p1.mailTo(),p1.mailCc(), p1.mailSubject(),'axapta report', true, p1.fileName(), fileName);
}
---------------------------
container CAP_parmSOPOConfirmEmail(container _conSysEmail = conSysEmail)
{
conSysEmail = _conSysEmail;
return conSysEmail;
}
---------------------------
server static void copyFile(FilenameOpen _attachmentFilename,
str _attachmentsFolder)
{
Set permissionSet;
;
// Revert permissions
CodeAccessPermission::revertAssert();
permissionSet = new Set(Types::Class);
permissionSet.add(new FileIoPermission(_attachmentFilename,'r'));
permissionSet.add(new FileIoPermission(_attachmentsFolder,'w'));
CodeAccessPermission::assertMultiple(permissionSet);
// Move to processed folder
// BP Deviation Documented
winAPI::copyFile(_attachmentFilename,_attachmentsFolder,true);
CodeAccessPermission::revertAssert();
}
---------------------------
How to Assert multiple file IO permission
server static void CAP_copyFile(FilenameOpen _attachmentFilename, str _attachmentsFolder)
{
Set permissionSet; ; // Revert permissions
CodeAccessPermission::revertAssert();
permissionSet = new Set(Types::Class);
permissionSet.add(new FileIoPermission(_attachmentFilename,'r'));
permissionSet.add(new FileIoPermission(_attachmentsFolder,'w'));
CodeAccessPermission::assertMultiple(permissionSet);
// Move to processed folder
// BP Deviation Documented
winAPI::copyFile(_attachmentFilename,_attachmentsFolder,true);
CodeAccessPermission::revertAssert();
}
{
Set permissionSet; ; // Revert permissions
CodeAccessPermission::revertAssert();
permissionSet = new Set(Types::Class);
permissionSet.add(new FileIoPermission(_attachmentFilename,'r'));
permissionSet.add(new FileIoPermission(_attachmentsFolder,'w'));
CodeAccessPermission::assertMultiple(permissionSet);
// Move to processed folder
// BP Deviation Documented
winAPI::copyFile(_attachmentFilename,_attachmentsFolder,true);
CodeAccessPermission::revertAssert();
}
Subscribe to:
Posts (Atom)