views:

1060

answers:

2

See also this question: http://stackoverflow.com/questions/447071/can-i-pass-a-system-net-mailmessage-to-a-wcf-service

I'd like to add attachments to the mail being sent. Attachments are either files on the local disc, or dynamically created Streams. A WCF contract can contain a Stream, but only when all arguments are of type Stream. So, what is the best way to pass one or more Attachments to a WCF service?

+6  A: 

Alright I've solved this myself. The trick here is to convert the attachment to a Base64 encodes string, much the same way email systems do this. I've created a class to handle this. Posted here for others:

 [DataContract]
    public class EncodedAttachment
    {
        [DataMember(IsRequired=true)]
        public string Base64Attachment;

        [DataMember(IsRequired = true)]
        public string Name;

        /// <summary>
        /// One of the System.Net.Mime.MediaTypeNames
        /// </summary>
        [DataMember(IsRequired = true)]
        public string MediaType;
    }

 public EncodedAttachment CreateAttachment(string fileName)
        {
            EncodedAttachment att = new EncodedAttachment();
            if (!File.Exists(fileName))
                throw new FileNotFoundException("Cannot create attachment because the file was not found", fileName);

            FileInfo fi = new FileInfo(fileName);
            att.Name = fi.Name;
            att.MediaType = System.Net.Mime.MediaTypeNames.Text.Plain;

            using (FileStream reader = new FileStream(fileName, FileMode.Open))
            {
                byte[] buffer = new byte[reader.Length];
                reader.Read(buffer, 0, (int)reader.Length);
                att.Base64Attachment = Convert.ToBase64String(buffer);
            }
            return att;
        }

And on the client side:

public void SendEmail(SmallMessage msg)
        {
            using (MailMessage message = new MailMessage())
            {
                message.Body = msg.Body;
                message.Subject = msg.Subject;
                message.To.Add(new MailAddress(msg.To));
                message.From = new MailAddress(msg.From);
                foreach (EncodedAttachment att in msg.Attachments)
                {
                    message.Attachments.Add(CreateAttachment(att));
                }

                SmtpClient client = new SmtpClient();
                client.Send(message);
            }
        }


Attachment CreateAttachment(EncodedAttachment encodedAtt)
{
    MemoryStream reader = new MemoryStream(Convert.FromBase64String(encodedAtt.Base64Attachment));
    Attachment att = new Attachment(reader, encodedAtt.Name, encodedAtt.MediaType);
    return att;            
}
edosoft
A: 

Hi Edo,

A couple of questions:

  • How did you set the binding/behavior configuration for thw WCF service?
  • Is it IIS or Windows service hosted?

I'm trying to host a mailing service inside a Windows service, but the e-mail is sent only when I stop the service - didn't find out why, no clues in the tracing logs. Any ideas?

Thanks,

casals
It's IIS based hosting. I'll post my config
edosoft
Thanks, Edo. Actually I already managed to get it to work on Windows hosting with basicHttpBinding - what I don't understand is why it only works when I host the service in a Windows 2008 environment. I'll open another post on this one. Thanks for your help.
casals