встраивание изображения в HTML-письмо

113

Я пытаюсь отправить составное / связанное HTML-письмо со встроенными изображениями в формате GIF. Это электронное письмо создано с использованием Oracle PL / SQL. Мои попытки не увенчались успехом, изображение отображается как красный крестик (в Outlook 2007 и почте Yahoo)

Я уже некоторое время отправляю электронные письма в формате html, но теперь мои требования заключаются в том, чтобы использовать в письме несколько изображений в формате GIF. Я могу хранить их на одном из наших веб-серверов и просто ссылаться на них, но многие пользователи почтовых клиентов не будут отображать их автоматически, и им нужно будет либо изменить настройки, либо вручную загружать их для каждого электронного письма.

Итак, мои мысли - встроить изображение. Мои вопросы:

  1. Что я здесь делаю не так?
  2. Правильный ли подход к встраиванию?
  3. Есть ли другие варианты, если мне нужно использовать все больше и больше изображений? Вложения не будут работать, поскольку изображения обычно представляют собой логотипы и значки, которые не имеют смысла вне контекста сообщения. Кроме того, некоторые элементы электронного письма являются ссылками на онлайн-систему, поэтому создание статического PDF-файла и его прикрепление не будут работать (насколько мне известно).

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

MIME-Version: 1.0
To: me@gmail.com
BCC: me@yahoo.com
From: email@yahoo.com
Subject: Test
Reply-To: email@yahoo.com
Content-Type: multipart/related; boundary="a1b2c3d4e3f2g1"

--a1b2c3d4e3f2g1

content-type: text/html;

    <html>
    <head><title>My title</title></head>
    <body>
    <div style="font-size:11pt;font-family:Calibri;">
    <p><IMG SRC="cid:my_logo" alt="Logo"></p>

... more html here ...

</div></body></html> 

--a1b2c3d4e3f2g1

Content-Type: image/gif;
Content-ID:<my_logo>
Content-Transfer-Encoding: base64
Content-Disposition: inline

[base64 image data here]

--a1b2c3d4e3f2g1--

Большое спасибо.

BTW: Да, я проверил, что данные base64 верны, так как я могу встроить изображение в сам html (используя тот же алгоритм для создания данных заголовка) и увидеть изображение в Firefox / IE.

Я также должен отметить, что это НЕ для спама, электронные письма отправляются определенным клиентам, которые ожидают его ежедневно. Контент основан на данных, а не на рекламе.

TBone
источник
Быстрый вопрос: размещаете ли вы эти изображения вне сайта или встраиваете их прямо в электронное письмо?
JonLim
Частично мой вопрос, я могу сделать то же самое. Я пытаюсь вставить их сюда, но безуспешно. Если я просто сделаю ссылку на них, многие пользователи не увидят изображения, не загрузив их предварительно, чего я бы хотел избежать.
tbone
1
Обычный <img src="URL" />сработал у меня, но это было изображение, которое я разместил за пределами сайта. Это не работает для вас?
JonLim
"работает" - это субъективно ... да, это работает, если пользователь желает загружать изображения каждый раз, но я бы хотел избежать этого и встроить изображение.
tbone
1
@JonLim: спасибо, что изучили это, посмотрите мои комментарии в ответе на то, что мне не хватало.
tbone

Ответы:

139

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

<img src="data:image/jpg;base64,{{base64-data-string here}}" />

И чтобы сделать этот пост полезным для других: Если у вас нет строки данных base64, легко создайте ее по адресу: http://www.motobit.com/util/base64-decoder-encoder.asp из файла изображения ,

Исходный код электронной почты выглядит примерно так, но я действительно не могу сказать вам, для чего нужна эта граница:

 To: email@email.de
 Subject: ...
 Content-Type: multipart/related;
 boundary="------------090303020209010600070908"

This is a multi-part message in MIME format.
--------------090303020209010600070908
Content-Type: text/html; charset=ISO-8859-15
Content-Transfer-Encoding: 7bit

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-15">
  </head>
  <body bgcolor="#ffffff" text="#000000">
    <img src="cid:part1.06090408.01060107" alt="">
  </body>
</html>

--------------090303020209010600070908
Content-Type: image/png;
 name="moz-screenshot.png"
Content-Transfer-Encoding: base64
Content-ID: <part1.06090408.01060107>
Content-Disposition: inline;
 filename="moz-screenshot.png"

[base64 image data here]

--------------090303020209010600070908--

// РЕДАКТИРОВАТЬ: О, я просто понимаю, что если вы вставите первый фрагмент кода из моего сообщения, чтобы написать письмо с помощью thunderbird, thunderbird автоматически изменит код html, чтобы он выглядел почти так же, как второй код в моем сообщении.

Бернд
источник
5
сначала попробовал, у меня это не работает для электронной почты. отлично работает для просмотра в IE / Firefox, но не отправляется по электронной почте.
tbone
Возможно, вы знаете способ (какой будет тип содержимого? Text / html? Заголовки электронной почты, которые мне нужно знать, чтобы отправить смешанный файл html / image таким образом)
tbone
1
@Zesty используйте @ [имя пользователя], чтобы предупредить кого-нибудь, только что увидел ваш вопрос. Использую utl_smtp. Для меня мне пришлось создать сборку с телом html, границами и т.д., а затем отправить через utl_smtp. См. Здесь простой пример: oracle-base.com/articles/misc/EmailFromOraclePLSQL.php Обратите внимание, что эта ссылка не показывает подход со встроенными изображениями, но содержит подробности, которые помогут вам начать работу.
tbone 09
41
URI данных в сообщениях электронной почты не поддерживаются многими основными клиентами и не должны использоваться, см .: campaignmonitor.com/blog/post/3927/…
Майкл Бёклинг,
2
В hotmail / icloud = вроде не работает (я что-нибудь пропустил
hsb1007
22

Другое решение - прикрепить изображение как вложение, а затем ссылаться на его html-код с помощью cid.

HTML-код:

<html>
    <head>
    </head>
    <body>
        <img width=100 height=100 id="1" src="cid:Logo.jpg">
    </body>
</html>

Код C #:

EmailMessage email = new EmailMessage(service);
email.Subject = "Email with Image";
email.Body = new MessageBody(BodyType.HTML, html);
email.ToRecipients.Add("abc@xyz.com");
string file = @"C:\Users\acv\Pictures\Logo.jpg";
email.Attachments.AddFileAttachment("Logo.jpg", file);
email.Attachments[0].IsInline = true;
email.Attachments[0].ContentId = "Logo.jpg";
email.SendAndSaveCopy();
Кхьяти Эльханс
источник
11

Я не нахожу здесь никаких полезных ответов, поэтому предлагаю свое решение.

  1. Проблема в том, что вы используете multipart/relatedтип контента, который в данном случае не подходит. Я использую multipart/mixedи внутри него multipart/alternative(работает на большинстве клиентов).

  2. Структура сообщения должна быть следующей:

    [Headers]
    Content-type:multipart/mixed; boundary="boundary1"
    --boundary1
    Content-type:multipart/alternative; boundary="boundary2"
    --boundary2
    Content-Type: text/html; charset=ISO-8859-15
    Content-Transfer-Encoding: 7bit
    [HTML code with a href="cid:..."]
    
    --boundary2
    Content-Type: image/png;
    name="moz-screenshot.png"
    Content-Transfer-Encoding: base64
    Content-ID: <part1.06090408.01060107>
    Content-Disposition: inline; filename="moz-screenshot.png"
    [base64 image data here]
    
    --boundary2--
    --boundary1--

Тогда это будет работать

Павел Перна
источник
Борюсь с этим. Я закодировал точно так же, как указано выше, но изображение не отображается (просто рамка с замещающим текстом; текст работает нормально). Мой Content-ID - это <filename.jpg>, поэтому мой href = "cid: filename.jpg" - есть ли какой-то особый трюк со значением или синтаксисом Content-ID и cid:?
Питер Флинн,
Я проверил RFC2392, и выражение CID оказалось действительным. Но он по-прежнему не отображается.
Питер Флинн,
Я написал ответ на аналогичный вопрос и создал ascii-арт для объяснения структуры: stackoverflow.com/a/40420648/633961
guettli
10

Если это не сработает, вы можете попробовать один из следующих инструментов, которые преобразуют изображение в таблицу HTML (однако помните о размере изображения):

Эрвин Майер
источник
10
img2hmtl - самое дурацкое решение / идея, которую я когда-либо видел. +1
Кристьян Лийва
4

Использование Base64 для встраивания изображений в HTML - это здорово. Тем не менее, обратите внимание, что строки base64 могут увеличить размер вашего электронного письма.

Следовательно,

1) Если у вас много изображений, загрузка изображений на сервер и загрузка этих изображений с сервера может уменьшить размер вашего электронного письма. (Вы можете получить множество бесплатных услуг через Google)

2) Если в вашем письме всего несколько изображений, использование строк base64 - определенно отличный вариант.

Помимо вариантов, предоставленных существующими ответами, вы также можете использовать команду для создания строки base64 в Linux:

base64 test.jpg
Брайан
источник
На что указал Майкл Бёклинг: URI данных в электронных письмах не поддерживаются во многих основных клиентах, таких как Gmail
Менди,
3

Я знаю, что это старый пост, но текущие ответы не касаются того факта, что Outlook и многие другие поставщики электронной почты не поддерживают встроенные изображения или изображения CID. Самый эффективный способ разместить изображения в электронных письмах - разместить их в Интернете и разместить ссылку на них в электронном письме. Для небольших списков рассылки отлично подойдет общедоступный Dropbox. Это также снижает размер электронной почты.

Скутер Кроуфорд
источник
2
  1. Чтобы встроенные изображения были полностью совместимы, вам нужны 3 границы.

  2. Все идет внутри multipart/mixed.

  3. Затем используйте, multipart/relatedчтобы содержать multipart/alternativeзаголовки ваших и ваших изображений.

  4. Наконец, включите свои загружаемые вложения в последнюю границу multipart/mixed.

Стивен Ньюман
источник
11
Было бы полезно, если бы вы включили пример.
Makyen
7
Еще более полезной была бы ссылка на спецификацию.
jbruni
2

На самом деле есть очень хороший пост в блоге, в котором перечислены плюсы и минусы трех различных подходов к этой проблеме Мартина Дэвиса. Вы можете прочитать его на https://sendgrid.com/blog/embedding-images-emails-facts/ .

Я хотел бы добавить четвертый подход с использованием фоновых изображений CSS.

Добавить

<div id="myImage"></div>

в тело электронной почты и класс css, например:

#myImage {
    background-image:  url('data:image/png;base64,iVBOR...[some more encoding]...rkggg==');
    width: [the-actual-image-width];
    height: [the-actual-image-height];
}
GerardV
источник
2

Для тех, кто не смог заставить одно из этих решений работать: Отправить встроенное изображение по электронной почте. Следуя шагам, изложенным в решении, предложенном @ T30, я смог отобразить встроенное изображение без блокировки Outlook (предыдущие методы были заблокированы) . Если вы используете обмен, как и мы, тогда также:

service = new ExchangeService(ExchangeVersion);
service.AutodiscoverUrl("email@domain.com");
SmtpClient smtp = new SmtpClient(service.Url.Host);

вам нужно будет передать его хосту URL-адреса службы обмена. Помимо этого, следующее решение должно позволить вам легко отправлять встроенные изображения.

tstrand66
источник
1

Может быть интересно, что и Outlook, и Outlook Express могут создавать эти форматы электронной почты с несколькими изображениями, если вы вставляете файлы изображений с помощью функции меню «Вставить / Изображение».

Очевидно, что тип электронной почты должен быть установлен на HTML (а не на обычный текст).

Любой другой метод (например, перетаскивание или любой вызов командной строки) приводит к отправке изображения (изображений) как вложения.

Если вы затем отправите такое письмо самому себе, вы увидите, как оно отформатировано! :)

FWIW, я ищу автономный исполняемый файл Windows, который выполняет встроенные изображения из режима командной строки, но, похоже, их нет. Это путь, по которому многие пошли ... Можно сделать это, скажем, с помощью Outlook Express, передав ему соответствующим образом отформатированный файл .eml.

Питер
источник
0

Ниже приведен рабочий код с двумя способами достижения этого:

using System;
using Outlook = Microsoft.Office.Interop.Outlook;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {

            Method1();
            Method2();
        }

        public static void Method1()
        {
            Outlook.Application outlookApp = new Outlook.Application();
            Outlook.MailItem mailItem = outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
            mailItem.Subject = "This is the subject";
            mailItem.To = "john@example.com";
            string imageSrc = "D:\\Temp\\test.jpg"; // Change path as needed

            var attachments = mailItem.Attachments;
            var attachment = attachments.Add(imageSrc);
            attachment.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x370E001F", "image/jpeg");
            attachment.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001F", "myident"); // Image identifier found in the HTML code right after cid. Can be anything.
            mailItem.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/id/{00062008-0000-0000-C000-000000000046}/8514000B", true);

            // Set body format to HTML

            mailItem.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
            string msgHTMLBody = "<html><head></head><body>Hello,<br><br>This is a working example of embedding an image unsing C#:<br><br><img align=\"baseline\" border=\"1\" hspace=\"0\" src=\"cid:myident\" width=\"\" 600=\"\" hold=\" /> \"></img><br><br>Regards,<br>Tarik Hoshan</body></html>";
            mailItem.HTMLBody = msgHTMLBody;
            mailItem.Send();
        }

        public static void Method2()
        {

            // Create the Outlook application.
            Outlook.Application outlookApp = new Outlook.Application();

            Outlook.MailItem mailItem = (Outlook.MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);

            //Add an attachment.
            String attachmentDisplayName = "MyAttachment";

            // Attach the file to be embedded
            string imageSrc = "D:\\Temp\\test.jpg"; // Change path as needed

            Outlook.Attachment oAttach = mailItem.Attachments.Add(imageSrc, Outlook.OlAttachmentType.olByValue, null, attachmentDisplayName);

            mailItem.Subject = "Sending an embedded image";

            string imageContentid = "someimage.jpg"; // Content ID can be anything. It is referenced in the HTML body

            oAttach.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E", imageContentid);

            mailItem.HTMLBody = String.Format(
                "<body>Hello,<br><br>This is an example of an embedded image:<br><br><img src=\"cid:{0}\"><br><br>Regards,<br>Tarik</body>",
                imageContentid);

            // Add recipient
            Outlook.Recipient recipient = mailItem.Recipients.Add("john@example.com");
            recipient.Resolve();

            // Send.
            mailItem.Send();
        }
    }
}
Тарик
источник
0

Еще одна подсказка к сообщению Павла Перна, которое мне очень помогло (не могу комментировать свою репутацию, поэтому я публикую это как ответ): в некоторых версиях Microsoft Exchange удалено встроенное расположение содержимого ( см. Этот пост от Microsoft ). Изображение просто не является частью письма, которое пользователь видит в Outlook. В качестве обходного пути используйте вместо этого «Content-Disposition: attachement». Outlook 2016 не будет отображать изображения как вложения, которые используются в почтовом сообщении, хотя они используют «Content-Disposition: attachement».

Klendatho
источник
-31

Если вы используете Outlook для отправки статического изображения с гиперссылкой, проще всего использовать Word.

  1. Откройте MS Word
  2. Скопируйте изображение на пустую страницу
  3. Добавить гиперссылку на изображение (Ctrl + K)
  4. Скопируйте изображение на свою электронную почту
Клаудио Виз
источник