As the title suggests, I want to Create an email from a template and attach a file. I also want the option to send the email or route to a queue for validation before manually hitting Send.
The purpose for the is an invoice process. Generate a batch of invoices, create a PDF from a PDF template , attach the file to a templated email etc…
Firstly, create an email from a template. The template has been created and is saved as an Email Template:
- // Create an e-mail message using a template.
- InstantiateTemplateRequest instTemplateReq = new InstantiateTemplateRequest
- {
- TemplateId = fetchTemplateId(LocalName),
- ObjectId = Id,
- ObjectType = "invoice"
- };
- InstantiateTemplateResponse instTemplateResp = null;
- Entity eMail = null;
- try
- {
- instTemplateResp = (InstantiateTemplateResponse)helper.Execute(instTemplateReq, true);
- }
- catch (Exception ex)
- {
- log.Write(this, "Failed to create email from template (using " + LocalName + ") " + ex.Message.ToString());
- }
Using the InstantiateTemplateRequest, I need to specify the templateid (derived the the PDF template name),the objectid (the previously created invoiceid) and the objecttype – the invoice.
The result is an email Entity:
- eMail = instTemplateResp.EntityCollection.Entities[0];
From this point I can create my PDF and attach:
- // Fetch invoicenumber and add to parameters
- string prefix = "topmostSubform[0].Page1[0].";
- string invno = fetchInvoiceNumber(Id);
- Parameters.Add(new PDFParameter() { PathName = prefix + "invno[0]", Value = invno });
- writeEmailAttachmentToCrm(emailId, "email", invno + ".pdf", createPDFArray(LocalName, Parameters));
Depending on the parameters passed I need to either SEND or ROUTE to an invoice queue for checking:
- if (Send)
- {
- // Send the email
- SendEmailRequest send = new SendEmailRequest();
- send.EmailId = emailId;
- send.TrackingToken = "";
- send.IssueSend = true;
- //SendEmailResponse sendEmailresp = (SendEmailResponse)helper.Execute(send, true);
- }
- else
- {
- // write to queue
- AddToQueueRequest routeRequest = new AddToQueueRequest
- {
- Target = new EntityReference("email", emailId),
- DestinationQueueId = Guid.Parse("3CEB6F78-2698-E111-9B55-782BCB776B8C")
- };
- helper.Execute(routeRequest, true);
- }
During testing , I’ve taken precautions to NOT send emails:
1. Comment out the SendRequest
2. Hardcode the partyIds
3. Hardcode the Queue
Hopefully this demonstrates how easy it is to send templated emails with attachments.
Oh Yes – the PDF routines – using iTextSharp:
- /// <summary>
- /// Create a PDFstream from a localfile
- /// </summary>
- /// <param name="LocalName"></param>
- /// <returns></returns>
- public PDFData CreatePDF(Guid Id, string LocalName, ObservableCollection<PDFParameter> Parameters)
- {
- PDFData returnData = new PDFData();
- string currentDir = AppDomain.CurrentDomain.BaseDirectory + @"Templates\";
- PdfReader reader = new PdfReader(currentDir + LocalName );
- // filling in the form
- MemoryStream op = new MemoryStream();
- PdfStamper stamp1 = new PdfStamper(reader, op);
- AcroFields form1 = stamp1.AcroFields;
- foreach (PDFParameter parameter in Parameters)
- {
- try
- {
- form1.SetField(parameter.PathName, parameter.Value);
- }
- catch (Exception ex)
- { }
- }
- stamp1.FormFlattening = true;
- stamp1.Close();
- returnData.Data = op.ToArray();
- returnData.Id = Id;
- op.Close();
- op.Dispose();
- reader.Close();
- return returnData;
- }
The PDF files are preformatted with placeholders (fields) to be substituted here .