• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1400
  • Last Modified:

Corrupt attachment sending with c#

Hello Experts,

When I want to send email with the code above with attachment I got corrupt attachemnt in the email, when I save it, it is 0 byte. What is the problem?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Net.Sockets;
using System.IO;
 
namespace MailService
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class SMailService : IMailService
    {
        private enum SMTPResponse : int
        {
            CONNECT_SUCCESS = 220,
            GENERIC_SUCCESS = 250,
            DATA_SUCCESS = 354,
            QUIT_SUCCESS = 221
        }
        private string CRLF = "\r\n";
        private int timeout = 10;
        public string SendMail(string encoding, string server, int port, bool htmlmail, string sender, string recipient, string subject, string body)
        {
            return MailSending(encoding, server, port, htmlmail, sender, recipient, subject, body, null, null, null);
        }
 
        public string SendMailWithAttachment(string encoding, string server, int port, bool htmlmail, string sender, string recipient, string subject, string body, string attachmentFileName, string base64EncodedAttachment, string attachmentMimeType)
        {
            return MailSending(encoding, server, port, htmlmail, sender, recipient, subject, body, attachmentFileName, base64EncodedAttachment, attachmentMimeType);
        }
 
        protected string MailSending(string encoding, string server, int port, bool htmlmail, string sender, string recipient, string subject, string body, string attachmentFileName, string base64EncodedAttachment, string attachmentMimeType)
        {
            try
            {
                TcpClient SmtpServ = new TcpClient();
                SmtpServ.Connect(server, port);
                NetworkStream nstSMTP = SmtpServ.GetStream();
                StreamWriter stwSMTP = new StreamWriter(nstSMTP);
                StreamReader strSMTP = new StreamReader(nstSMTP);
 
                //Server is ready
                if (!Check_Response(nstSMTP, strSMTP, SMTPResponse.CONNECT_SUCCESS))
                    throw new FaultException<MailError>(new MailError { Text = "Server is not ready" });
 
                //Say hello to server
                Senddata(stwSMTP, "HELO server");
                if (!Check_Response(nstSMTP, strSMTP, SMTPResponse.GENERIC_SUCCESS))
                    throw new FaultException<MailError>(new MailError { Text = "Server did not respond 250 after HELO" });
 
                //Set the sender
                Senddata(stwSMTP, string.Format("MAIL From: {0}", sender));
                if (!Check_Response(nstSMTP, strSMTP, SMTPResponse.GENERIC_SUCCESS))
                    throw new FaultException<MailError>(new MailError { Text = "Server did not respond 250 after MAIL FROM" });
 
                //Set the recipient
                Senddata(stwSMTP, string.Format("RCPT TO: {0}", recipient));
                if (!Check_Response(nstSMTP, strSMTP, SMTPResponse.GENERIC_SUCCESS))
                    throw new FaultException<MailError>(new MailError { Text = "Server did not respond 250 after RCPT TO" });
 
                //Build the header
                Senddata(stwSMTP, "DATA");
                if (!Check_Response(nstSMTP, strSMTP, SMTPResponse.DATA_SUCCESS))
                    throw new FaultException<MailError>(new MailError { Text = "Server did not respond 354 after DATA" });
                Senddata(stwSMTP, "From: " + sender);
                Senddata(stwSMTP, "To: " + recipient);
                Senddata(stwSMTP, string.Format("Subject: =?{0}?B?{1}?=", encoding, base64Encode(subject)));
                string MsgBody = body;
                if (attachmentMimeType == null || attachmentFileName == null || base64EncodedAttachment == null)
                {
                    if (htmlmail)
                        Senddata(stwSMTP, "Content-Type: text/html; charset=" + encoding + ";");
                    else
                        Senddata(stwSMTP, "Content-Type: text/plain; charset=" + encoding + ";");
                    Senddata(stwSMTP, "Content-Transfer-Encoding: base64");
                    Senddata(stwSMTP, base64Encode(MsgBody));
                }
                else
                {
                    Senddata(stwSMTP, "MIME-Version: 1.0");
                    Senddata(stwSMTP, "Content-Type: multipart/mixed; boundary=\"unique_boundary_1\"");
                    Senddata(stwSMTP, "This is a multi-part message in MIME format.");
                    Senddata(stwSMTP, "--unique_boundary_1");
                    if (htmlmail)
                        Senddata(stwSMTP, "Content-Type: text/html; charset=" + encoding + ";");
                    else
                        Senddata(stwSMTP, "Content-Type: text/plain; charset=" + encoding + ";");
                    Senddata(stwSMTP, "Content-Transfer-Encoding: base64");
                    Senddata(stwSMTP, base64Encode(MsgBody));
                    Senddata(stwSMTP, "--unique_boundary_1");
                    Senddata(stwSMTP, string.Format("Content-Type: {0}; file={1}", attachmentMimeType, attachmentFileName));
                    Senddata(stwSMTP, "Content-Transfer-Encoding: base64");
                    Senddata(stwSMTP, string.Format("Content-Disposition: attachment; filename={0}", attachmentFileName));
                    for(int i=0;i<base64EncodedAttachment.Length;)
                    {
                        int nextchunk=100;
                        if(base64EncodedAttachment.Length - (i + nextchunk ) <0)
                            nextchunk = base64EncodedAttachment.Length -i;
                        Senddata(stwSMTP, base64EncodedAttachment.Substring(i, nextchunk));
                        i+=nextchunk;
                    }           
                    Senddata(stwSMTP, "--unique_boundary_1--");
                }
                Senddata(stwSMTP, ".");
                if (!Check_Response(nstSMTP, strSMTP, SMTPResponse.GENERIC_SUCCESS))
                    throw new FaultException<MailError>(new MailError { Text = "Server did not respond 250 after sending DATA" });
 
                //Send quit
                Senddata(stwSMTP, "QUIT");
                Check_Response(nstSMTP, strSMTP, SMTPResponse.QUIT_SUCCESS);
                stwSMTP.Close();
                strSMTP.Close();
                nstSMTP.Close();
                SmtpServ.Close();
            }
            catch (FaultException<MailError> ex) { return ex.Detail.Text; }
            catch (FaultException<GeneralError> ex) { return ex.Detail.Text; }
            catch (IOException ex)
            {
                return "IO error, message is: " + ex.Message;
            }
            catch (Exception ex)
            {
                return "General error, message is: " + ex.Message;
            }
            return "success";
        }
 
        private string base64Encode(string data)
        {
            try
            {
                byte[] encData_byte = new byte[data.Length];
                encData_byte = System.Text.Encoding.Default.GetBytes(data);
                string encodedData = Convert.ToBase64String(encData_byte);
                return encodedData;
            }
            catch (Exception ex)
            {
                throw new FaultException<GeneralError>(new GeneralError { Text = "Error in base64Encode, message is: " + ex.Message });
            }
        }
        private bool Check_Response(NetworkStream n, StreamReader s, SMTPResponse response_expected)
        {
            DateTime timeoutCheck = DateTime.Now;
            TimeSpan tsp = DateTime.Now - timeoutCheck;
            while (tsp.Seconds < timeout)
            {
                if (!n.DataAvailable)
                {
                    tsp = DateTime.Now - timeoutCheck;
                    continue;
                }
                string response = s.ReadLine();
                string expected = ((int)response_expected).ToString();
                if (response.Substring(0, expected.Length).Equals(expected))
                    return true;
                return false;
            }
            return false;
        }
        private void Senddata(StreamWriter s, string msg)
        {
            s.WriteLine(msg);
            s.Flush();
        }
    }
    public class MailError
    {
        public string Text { get; set; }
    }
    public class GeneralError
    {
        public string Text { get; set; }
    }
}

Open in new window

0
develc
Asked:
develc
1 Solution
 
Éric MoreauSenior .Net ConsultantCommented:
have you tried not to encode your attachments?
0
 
pivarCommented:
Hi,

Could you use SmtpClient in System.Net.Mail? Or is there a reason why you wouldnt want to?

/peter
0
 
develcAuthor Commented:
The reason I use this, because it is going to be a wcf service, and I will send the attachment via base64 encoded text. And MailAttachment class does not support direct text input, just filename.

BTW I found the solution: There must be an empty line before the encoded file.
So on line 95:  Senddata(stwSMTP, string.Format("Content-Disposition: attachment; filename={0}"+CRLF, attachmentFileName));  is correct.
                   
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now