2012-11-04 8 views
8

У меня есть файл excel (формат Excel 2003/xls), и я хочу отправить его по электронной почте с помощью C#. Мой код отправляет его успешно, но когда я пытаюсь открыть файл ответов, он, похоже, ошибочно закодирован.Как отправить файл Excel по электронной почте?

Для примера здесь является ответом файла:

= _utf-8_B_RWxzesOhbW9sw6FzXzIwMTJfMTBfMTZf.dat

А вот сам файл ответов:

= UTF-8? B? VEdWdmJIWmhjMkZ1Wk1Pelh6UXlYekZmPz0NCiA9P3V0Zi04P0I/VGtW? = \ \ =? Utf-8? B? TlgwZFRXaTU0YkhNPT89? = "Content-Transfer-Encoding: base64 Conten т-Disposition: вложение

0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPgADAP7/CQAGAAAAAAAAAAAAAAABAAAA AQAAAAAAAAAAEAAAIwAAAAEAAAD + //// AAAAAAAAAAD ///////////////////// ///////// ////////////////////////////////////////////////// ///// //////////////////////////////

Это мой код фрагмент:

... 
var attachment = new Attachment(WriteFileToMemory("fileFullPath"), "fileName.xls"); 
attachment.ContentType = new ContentType("application/vnd.ms-excel"); 
attachmentCollection.Add(attachment); 
... 


private Stream WriteFileToMemory(string filePath) 
{ 
    var memoryStream = new MemoryStream(); 
    _openedStreams.Add(memoryStream); 
    using (var file = new FileStream(filePath, FileMode.Open, FileAccess.Read)) 
    { 
     var bytes = new byte[file.Length]; 
     file.Read(bytes, 0, (int) file.Length); 
     memoryStream.Write(bytes, 0, (int) file.Length); 
     file.Close(); 
    } 
    memoryStream.Position = 0; 
    return memoryStream; 
} 

Как я могу установить тип кодировки вложения и какую кодировку следует использовать с файлами Excel?

Пожалуйста, помогите мне решить эту проблему. Спасибо заранее.

+6

Почему бы вам не сделать: 'new Attachment (новый FileStream (« путь », FileMode.Open, FileAccess.Read),« fileName.xls »)'? – Magnus

+0

Да, ты прав. Теперь я использую ваше решение для загрузки файла, но проблема все та же. Он может отправлять почту, но кодировка файла excel неверна. – ZYD

ответ

1

Я нашел решение:

... 
var attachment = CreateAttachment(WriteFileToMemory(Common.TempPath + excelName), excelName); 
attachmentCollection.Add(attachment); 
... 

private Stream WriteFileToMemory(string filePath) 
{ 
    var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); 
    _openedStreams.Add(fileStream); 
    return fileStream; 
} 

public static Attachment CreateAttachment(Stream attachmentFile, string displayName) 
{ 
    var attachment = new Attachment(attachmentFile, displayName); 
    attachment.ContentType = new ContentType("application/vnd.ms-excel"); 
    attachment.TransferEncoding = TransferEncoding.Base64; 
    attachment.NameEncoding = Encoding.UTF8; 
    string encodedAttachmentName = Convert.ToBase64String(Encoding.UTF8.GetBytes(displayName)); 
    encodedAttachmentName = SplitEncodedAttachmentName(encodedAttachmentName); 
    attachment.Name = encodedAttachmentName; 
    return attachment; 
} 

private static string SplitEncodedAttachmentName(string encoded) 
{ 
    const string encodingtoken = "=?UTF-8?B?"; 
    const string softbreak = "?="; 
    const int maxChunkLength = 30; 
    int splitLength = maxChunkLength - encodingtoken.Length - (softbreak.Length * 2); 
    IEnumerable<string> parts = SplitByLength(encoded, splitLength); 
    string encodedAttachmentName = encodingtoken; 
    foreach (var part in parts) 
    { 
     encodedAttachmentName += part + softbreak + encodingtoken; 
    } 
    encodedAttachmentName = encodedAttachmentName.Remove(encodedAttachmentName.Length - encodingtoken.Length, encodingtoken.Length); 
    return encodedAttachmentName; 
} 

private static IEnumerable<string> SplitByLength(string stringToSplit, int length) 
{ 
    while (stringToSplit.Length > length) 
    { 
     yield return stringToSplit.Substring(0, length); 
     stringToSplit = stringToSplit.Substring(length); 
    } 
    if (stringToSplit.Length > 0) 
    { 
     yield return stringToSplit; 
    } 
} 

Исходя из этого источника:http://social.msdn.microsoft.com/Forums/en-US/dotnetframeworkde/thread/b6c764f7-4697-4394-b45f-128a24306d55

5

Вы делаете это слишком сложным, как указывает @Magnus, new Attachment() может обрабатывать FileStream s, так что просто передайте новый фильтр в конструктор.

... 
var attachment = new Attachment(File.Open("fileFullPath", FileMode.Open), "fileName.xls"); 
attachment.ContentType = new ContentType("application/vnd.ms-excel"); 
attachmentCollection.Add(attachment); 
... 

Слово предупреждения, хотя, вроде не по теме, вы не можете отправить почту, как, что несколько раз, так как поток не всегда будет сбросить себя должным образом.

+0

Что вы подразумеваете под потоком, не всегда будет правильно сбрасываться? Я собираю потоки в коллекцию, и после того, как SmtpClient отправил почту, я могу закрыть открытые потоки, поэтому я могу удалить временный файл, который я прикреплял к почте. – ZYD

+0

@ ZYD Только это, если вы создаете почту с приложением и отправляете ее, а для somemason храните почту в случае, если вы хотите повторно отправить ее через 5 минут, поток не будет сбрасываться должным образом. Поэтому создайте почту и отправьте ее, не храните письма после их создания. – flindeberg

+0

Чтобы сбросить поток, используйте stream.Position = 0; – Hackworth

0

сообщение электронной почты имя приложения, которое содержит не-ASCII символов и длиннее 41 UTF-8 кодируются байт закодирован два раза перед передачей в приложении, которое скомпилировано для .NET Framework 4. Эта проблема возникает из-за проблемы в .NET Framework 4. Кодировки SMTP были переписаны, чтобы включить правильное свертывание в соответствии с стандартами RFC пределов длины строки. Это поведение вставляет дополнительные символы возврата строки каретки (CRLF), если строка имени слишком длинная. Эти дополнительные управляющие символы заставляют имя вложения снова кодироваться.Чем больше вы можете найти здесь http://support.microsoft.com/kb/2402064

1

Я разрешающую ту же проблему, исправляя MailMessage свойства:

bool SendEmail(string subject, string message, Attachment attachment) 
{ 
    try 
    { 
     SmtpClient smtpClient = CreateProductionSMTPClient(); 
     MailMessage msg = new MailMessage(); 
     msg.Subject = subject; 
     msg.Body = message; 
     msg.To.Add(ConfigurationHelper.EmailTo); 
     msg.From = new MailAddress(ConfigurationHelper.EmailFrom); 
     msg.BodyEncoding = Encoding.UTF8; 

     //commented line cause the problem 
     // msg.Headers.Add("Content-Type", "text/html"); 
     //instead of that use next line 
     msg.IsBodyHtml = true; 

     if (attachment != null) 
     { 
      msg.Attachments.Add(attachment); 
     } 

     smtpClient.Send(msg); 
     return true; 
    } 
    catch (Exception ex) 
    { 
     return false; 
    } 
} 

//Attachment building 
Attachment WrapExcelBytesInAttachment(byte[] excelContent) 
{ 
    try 
    { 
     Stream stream = new MemoryStream(excelContent); 
     Attachment attachment = new Attachment(stream, "fileName.xls"); 
     attachment.ContentType = new ContentType("application/vnd.ms-excel"); 
     return attachment; 
    } 
    catch (Exception ex) 
    { 
     return null; 
    } 
} 
1

В случае, если вы хотите, чтобы генерировать Excel из DataTable, и отправить его по почте, вы можете приложить первенствует файл следующим образом:

Workbook theWorkbook = new Workbook(); 
theWorkbook.SetCurrentFormat(WorkbookFormat.Excel2007); 
Worksheet theWorkSheet = theWorkbook.Worksheets.Add("Sheet1"); 

int iRow = 0; 
int iColumn = 0; 
theWorkSheet.Rows[0].CellFormat.Font.Bold = ExcelDefaultableBoolean.True; 

//Titles 
foreach (DataColumn column in DataTable.Columns) 
{ 
    theWorkSheet.Rows[iRow].Cells[iColumn].Value = column.ColumnName; 
    iColumn++; 
} 

//Values 
foreach (DataRow row in DataTable.Rows) 
{ 
    iColumn = 0; 
    iRow++; 

    foreach (var item in row.ItemArray) 
    { 
     theWorkSheet.Rows[iRow].Cells[iColumn].Value = item.ToString(); 
     iColumn++; 
    }      
} 
System.IO.MemoryStream theStream = new System.IO.MemoryStream(); 
theWorkbook.Save(theStream); 
byte[] byteArr = theStream.ToArray(); 
System.IO.MemoryStream stream1 = new System.IO.MemoryStream(byteArr, true); 
stream1.Write(byteArr, 0, byteArr.Length); 
stream1.Position = 0; 
message.Attachments.Add(new Attachment(stream1, "filename.xlsx")); 

Он работал для меня, по крайней мере с платформой .NET 4 и Excel 2016.

с уважением.

+1

'stream.Position = 0;' это линия, которая мне помогла. без него мое вложение было всего лишь 504 байта вместо некоторых kBs –

Смежные вопросы