Ice.Mail.SmtpMailer issues with attachments

Hey Epigurus,

I’ve been asked to add an attachment link to some notification emails (sent via BPM), and since we don’t have the APR module I unfortunately couldn’t just check the “Include shortcut link”.

I’ve used the methods described in URL's to either full Epicor client or Web Access? - #13 by josecgomez , where I have a .sysconfig file template (with the shortcut tags) that gets updated in a BPM to the respective recordID, then attached and sent via email with Ice.Mail.SmtpMailer (Server Side Programming for Email Generation - #3 by Jason_Woods was used for the attachment portion)

The email will work (the email gets sent when a user is assigned a Corrective Action), but then an IO exception gets thrown when I try to delete the attachment file. After further testing, it looks like it is because the file is still in use by the SmtpMailer.

Any suggestions on how I can resolve this issue? I was hoping the using(){} would help to do the disposing/filestream closing, but it doesn’t help me here. Not sure if/where I may have gone wrong.

Here’s the portion of the code I’m having the issues with:

// Send Email
using( Ice.Mail.SmtpMailer mailer = new Ice.Mail.SmtpMailer(this.Session))
{
  var message = new Ice.Mail.SmtpMail();
  
  message.SetFrom( GetCompanyAddressAction(ttDMRCorAct_Row.Company) );
  message.SetTo(EmailTO);
  message.SetCC(EmailCC);
  message.SetBcc(EmailBCC);
  message.SetSubject(EmailSubject);
  message.SetBody(EmailBody);
  message.IsBodyHtml = true;
  //Add Attachments
  Dictionary<string, string> attachments = new Dictionary<string, string>();
  attachments.Add("AttachmentInfo", attachmentPath);
  //Send 
  mailer.Send(message, attachments);
}
File.Delete(attachmentPath); //file does not get deleted here, IO error is thrown
1 Like

I was able to get the stream to close using one of the other .send methods, which uses an actual Stream instead of the file path in a string (and then putting that Stream in another using statement). Crisis averted.

using( Ice.Mail.SmtpMailer mailer = new Ice.Mail.SmtpMailer(this.Session))
{  
    using( FileStream attachmentStream = File.Open(attachmentPath, FileMode.Open))
    {
    var message = new Ice.Mail.SmtpMail();
    message.SetFrom( GetCompanyAddressAction(ttDMRCorAct_Row.Company) );
    message.SetTo(EmailTO);
    message.SetCC(EmailCC);
    message.SetBcc(EmailBCC);
    message.SetSubject(EmailSubject);
    message.SetBody(EmailBody);
    message.IsBodyHtml = true;
    //Add Attachments
    Dictionary<string, Stream> attachments = new Dictionary<string, Stream>();
    attachments.Add("CorrectiveAction" + ttDMRCorAct_Row.ActionID.ToString() + ".sysconfig" , attachmentStream);
    //Send 
    mailer.Send(message, attachments);
    }
}

File.Delete(attachmentPath);

@Asz0ka, can you please send me this BPM I am trying to attach a sharepoint file with email but it’s not working for me.

Sure, it’s a UBAQ Method Directive so it can run on a schedule. Most of the email code is already posted above. Sharepoint may be the issue.

// Initialize Actions
Func<string, string> GetCompanyAddressAction = (CompanyID) => {

  var Company_Row =
    (from sc in Db.SysCompany.With(LockHint.NoLock)
    where sc.Company == CompanyID
    select new { sc.EmailFromAddr, sc.EmailFromLabel }).FirstOrDefault();

  if (Company_Row != null) {
    return string.Format(@"""{0}"" <{1}>", Company_Row.EmailFromLabel.Trim(), Company_Row.EmailFromAddr.Trim());
  }

  return string.Empty;
};

foreach(var ttResults_Row in ttResults) {
  // Initialize Variables
  string EmailTO = "";
  string EmailCC = "emailrecipientsgoehere@mail.com";
  string EmailBCC = "";
  string EmailSubject = "";
  string EmailBody = "";


  if (ttResults_Row != null)
  {    
  
      string templatePath = @"\\filepath";
      string attachmentPath = @"\\filepath" + ttResults_Row.DMRCorAct1_ActionID.ToString() + @".sysconfig";
      
      //Edit shortcut file attachment to point to correct CAR
      string text = File.ReadAllText(templatePath);
      text = Regex.Replace(text, @"<RecordID>\d*</RecordID>", @"<RecordID>" + ttResults_Row.DMRCorAct1_ActionID.ToString() + @"</RecordID>");
      File.WriteAllText(attachmentPath, text);
      text = "";
      text = null;

      EmailSubject = "Corrective Action Due - ActionID: " + ttResults_Row.DMRCorAct1_ActionID + " - Due Date: " + ttResults_Row.DMRCorAct_DuDate;
      
      EmailBody = "The corrective action request (ActionID: " + ttResults_Row.DMRCorAct1_ActionID +") that was assigned to you is due as of " + ttResults_Row.DMRCorAct_DuDate + ".<br>You can view the request by opening the link attached, or from the 'Corrective Action Request' Module in Epicor.<br><br>Once complete, enter the 'Action Complete' date in the Corrective Action Module to move the process forward.<br><br>Brief Overview:<br>" +  ttResults_Row.DMRCorAct_Description;
      
      EmailTO = ttResults_Row.EmpBasic_EMailAddress; //uncomment for golive
      
      if(EmailTO != "") {
        // Send Email
        using( Ice.Mail.SmtpMailer mailer = new Ice.Mail.SmtpMailer(this.Session))
        {  
            using( FileStream attachmentStream = File.Open(attachmentPath, FileMode.Open))
            {
            var message = new Ice.Mail.SmtpMail();
            message.SetFrom( GetCompanyAddressAction("93546") );
            message.SetTo(EmailTO);
            message.SetCC(EmailCC);
            message.SetBcc(EmailBCC);
            message.SetSubject(EmailSubject);
            message.SetBody(EmailBody);
            message.IsBodyHtml = true;
            //Add Attachments
            Dictionary<string, Stream> attachments = new Dictionary<string, Stream>();
            attachments.Add("CorrectiveAction" + ttResults_Row.DMRCorAct1_ActionID.ToString() + ".sysconfig" , attachmentStream);
            //Send 
            mailer.Send(message, attachments);
            }
        }
        
      }
      File.Delete(attachmentPath);
   }
}

Directive usings and references:

using System;
using System.IO;
using System.Text.RegularExpressions;
1 Like