Я хочу отправлять письма с изображениями в них. Написанный мной код работает нормально, но по какой-то неизвестной мне причине он не работает с клиентами Outlook. Я отправил тестовое письмо (слева: Thunderbird, справа: Outlook):

Mail as seen in a Thunderbird client Mail as seen in an Outlook client

Что должен делать мой код: он берет RTF из RichTextBox и преобразует его в HTML. Это оставляет изображения встроенными в HTML в виде строк base64. Я извлекаю все изображения в кодировке base64 одно за другим и помещаю их в MemoryStream, который принимает LinkedResource. Поскольку почтовые клиенты обычно не принимают встроенные изображения, я заменяю встроенное изображение в HTML на идентификатор содержимого. Затем я устанавливаю некоторые свойства LinkedResource и добавляю их в AlternateView. Этот альтернативный вид затем добавляется в System.Net.Mail.MailMessage, и письмо отправляется. Соответствующий код:

MemoryStream mem = null;
private readonly Regex embeddedImageRegex = new Regex("src=\"data:image/.*?\"");

public MyHTMLMailMessage() 
    : base()
{
    this.SubjectEncoding = Encoding.UTF8;
    this.BodyEncoding = Encoding.UTF8;
    this.IsBodyHtml = true;
}

public bool Send()
{
    // create HTML View with images
    AlternateView htmlView = AlternateView.CreateAlternateViewFromString(HTML, System.Text.Encoding.UTF8, MediaTypeNames.Text.Html);
    ReplaceEmbeddedImagesWithCID(htmlView);
    this.AlternateViews.Add(htmlView);

    this.Body = HTML;

    SmtpClient client = new SmtpClient(server, port);
    client.DeliveryMethod = SmtpDeliveryMethod.Network;
    client.UseDefaultCredentials = String.IsNullOrEmpty(username);

    try
    {
        client.Send(this);
        return true;
    }
    catch (SmtpException e)
    {
        return false;
    }
    finally
    {
        mem?.Close();
    }
}

private void ReplaceEmbeddedImagesWithCID(AlternateView altView)
{
    string extension;
    int imageIndex = 0;
    string contentID = $"image{imageIndex}";

    // go through every base64 string, create a content id and LinkedResource for it
    while (embeddedImageRegex.IsMatch(HTML))
    {
        extension = new Regex("image/.*?;").Match(HTML).Value
                    .Replace("image/", "")
                    .Replace(";", "");

        string base64img = embeddedImageRegex.Match(HTML).Value
                            .Replace("src=\"", "")
                            .Replace("\"", "")
                            .Split(',')[1];
        HTML = embeddedImageRegex.Replace(HTML, $"src=\"cid:image{imageIndex}\"", 1);

        byte[] byBitmap = Convert.FromBase64String(base64img);
        mem = new MemoryStream(byBitmap);
        mem.Position = 0;
        
        LinkedResource linkedImage = new LinkedResource(mem, $"image/{extension}");
        linkedImage.ContentId = contentID;

        altView.LinkedResources.Add(linkedImage);
        altView = AlternateView.CreateAlternateViewFromString(HTML, null, MediaTypeNames.Text.Html);
        imageIndex++;
    }
}

Итак, я пробовал разные решения, но ни одно из них не сработало. Мои шаги до сих пор:

  1. Я редактировал некоторые регистрационные ключи в HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\x.0\Outlook\Options\Mail или HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\x.0\Common

  2. Я оставил изображение как строку base64 в HTML

  3. Были добавлены некоторые свойства

linkedImage.TransferEncoding = TransferEncoding.Base64;
linkedImage.ContentType.Name = contentID;
linkedImage.ContentLink = new Uri($"cid:{contentID}");
this.Headers.Add("Content-ID", $"<image{imageIndex}>");
this.Headers.Add("X-Attachment-Id", $"image{imageIndex}");
altView.TransferEncoding = TransferEncoding.QuotedPrintable;

У меня ничего из этого не сработало, хотя казалось, что это помогло другим. Я что-то упустил?

0
HimmDawg 30 Мар 2021 в 14:46

2 ответа

Лучший ответ

Образы Base64 по умолчанию заблокированы в Outlook.

Вам необходимо прикрепить изображения к электронному письму и установить свойство PR_ATTACH_CONTENT_ID в электронном письме (имя DASL - "http://schemas.microsoft.com/mapi/proptag/0x3712001E"). См. Встраивание изображений в новые сообщения с помощью макроса за дополнительной информацией.

0
Eugene Astafiev 30 Мар 2021 в 17:28

Подтвердили ли вы, что это не блок изображений из настроек центра управления безопасностью.

Разблокировать загрузку изображений для одного сообщения: Щелкните информационную панель вверху сообщения. Щелкните Загрузить изображения.

Разблокировать загрузку изображений для всех сообщений: Outlook 2007 В меню «Инструменты» щелкните Центр управления безопасностью> Автоматическая загрузка. Снимите флажок «Не загружать изображения автоматически в сообщениях электронной почты HTML или в элементах RSS».

Outlook 2010 и более поздние версии: На вкладке «Файл» щелкните Параметры> Центр управления безопасностью. В Центре управления безопасностью Microsoft Outlook щелкните Параметры центра управления безопасностью. Снимите флажок «Не загружать изображения автоматически в сообщениях электронной почты HTML или в элементах RSS».

Разблокируйте загрузку изображений для всех сообщений с определенного адреса электронной почты или домена: В открытом сообщении, отправленном с определенного адреса электронной почты или домена, щелкните правой кнопкой мыши заблокированный элемент. Выполните одно из следующих:

  • Щелкните Добавить отправителя в список надежных отправителей.
  • Щелкните Добавить домен [@domain] в список надежных отправителей.
0
sholistudios 30 Мар 2021 в 12:04