osadzanie obrazu w e-mailu html


113

Próbuję wysłać wieloczęściową / pokrewną wiadomość e-mail w formacie HTML z osadzonymi obrazami gif. Ten e-mail jest generowany przy użyciu Oracle PL / SQL. Moje próby nie powiodły się, a obraz jest wyświetlany jako czerwony znak X (w programie Outlook 2007 i poczcie yahoo)

Od jakiegoś czasu wysyłam e-maile w formacie html, ale teraz wymagam użycia kilku obrazów gif w e-mailu. Mogę je przechowywać na jednym z naszych serwerów internetowych i po prostu łączyć się z nimi, ale wielu klientów poczty e-mail nie wyświetla ich automatycznie i będą musieli zmienić ustawienia lub ręcznie pobrać je dla każdego e-maila.

Więc myślę o osadzeniu obrazu. Moje pytania to:

  1. Co ja tu robię źle?
  2. Czy podejście osadzania jest właściwe?
  3. Czy są jakieś inne opcje, jeśli muszę używać coraz więcej obrazów? Załączniki nie będą działać, ponieważ obrazy to zazwyczaj logo i ikony, które nie mają sensu w kontekście wiadomości. Ponadto niektóre elementy wiadomości e-mail są odsyłaczami do systemu online, więc generowanie statycznego pliku PDF i załączanie go nie będzie działać (i tak o ile wiem).

skrawek:

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--

Wielkie dzięki.

BTW: Tak, zweryfikowałem, że dane base64 są poprawne, ponieważ mogę osadzić obraz w samym html (używając tego samego algo do tworzenia danych nagłówka) i zobaczyć obraz w przeglądarce Firefox / IE.

Powinienem również zauważyć, że NIE jest to spam, e-maile są wysyłane do określonych klientów, którzy oczekują go codziennie. Treść jest oparta na danych, a nie reklamach.


Szybkie pytanie: czy udostępniasz te obrazy poza witryną, czy też umieszczasz je bezpośrednio w wiadomości e-mail?
— JonLim,

Część mojego pytania naprawdę mogę zrobić. Próbuję je tutaj osadzić, ale bezskutecznie. Jeśli podam link do nich, wielu użytkowników nie zobaczy obrazów bez ich wcześniejszego pobrania, czego chciałbym uniknąć.
— tbone

1
Zwykły <img src="URL" />działał dla mnie, ale był to obraz, który umieściłem na serwerze. To ci nie pasuje?
— JonLim,

„działa” jest subiektywne ... tak, działa, jeśli użytkownik chce pobrać obrazy za każdym razem, ale chciałbym tego uniknąć i osadzić obraz.
— tbone

1
@JonLim: dzięki za przyjrzenie się temu, zobacz moje komentarze w odpowiedzi na to, czego mi brakowało.
— tbone

Odpowiedzi:


139

Spróbuj wstawić go bezpośrednio, w ten sposób możesz wstawić wiele obrazów w różnych miejscach w e-mailu.

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

I aby ten post był przydatny dla innych, aby: Jeśli nie masz ciągu danych base64, utwórz go łatwo pod adresem : http://www.motobit.com/util/base64-decoder-encoder.asp z pliku obrazu .

Kod źródłowy wiadomości e-mail wygląda mniej więcej tak, ale naprawdę nie mogę powiedzieć, do czego służy ta granica:

 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--

// EDYCJA: Och, po prostu zdaję sobie sprawę, że jeśli wstawisz pierwszy fragment kodu z mojego postu, aby napisać wiadomość e-mail za pomocą thunderbirda, thunderbird automatycznie zmieni kod HTML, aby wyglądał prawie tak samo jak drugi kod w moim poście.


5
próbowałem najpierw tego, nie działa dla mnie w przypadku poczty e-mail. działa dobrze do przeglądania w IE / Firefox, ale nie jest wysyłany jako e-mail.
— tbone

Być może znasz sposób (jaki byłby typ zawartości? Text / html? Nagłówki e-maili, które muszę wiedzieć, aby wysłać mieszany plik HTML / obraz w ten sposób)
— tbone.

1
@Zesty użyj @ [nazwa użytkownika], aby kogoś ostrzec, właśnie zobaczyłem Twoje pytanie. Używam utl_smtp. Dla mnie musiałem stworzyć clob z treścią html, granicami itp., A następnie wysłać przez utl_smtp. Zobacz tutaj, aby zapoznać się z prostym przykładem: oracle-base.com/articles/misc/EmailFromOraclePLSQL.php Zauważ, że ten link nie pokazuje podejścia do osadzonych obrazów, ale zawiera szczegóły, które pomogą Ci przejść.
— tbone

41
Identyfikatory URI danych w wiadomościach e-mail nie są obsługiwane w wielu popularnych klientach i nie powinny być używane, patrz: campaignmonitor.com/blog/post/3927/ ...
— Michael Böckling

2
Wygląda na to, że nie działa w hotmail / icloud = (czy coś przegapiłem
— hsb1007

22

Innym rozwiązaniem jest dołączenie obrazu jako załącznika, a następnie odwołanie się do niego w kodzie html za pomocą cid.

Kod HTML:

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

Kod 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

Żadna z odpowiedzi nie jest dla mnie przydatna, więc przedstawiam moje rozwiązanie.

  1. Problem polega na tym, że używasz multipart/relatedjako typu zawartości, co w tym przypadku nie jest dobre. Używam multipart/mixedi wewnątrz multipart/alternative(działa na większości klientów).

  2. Struktura wiadomości powinna wyglądać następująco:

    [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--
    

Wtedy zadziała


Walczę o to. Zakodowałem dokładnie tak, jak powyżej, ale obraz się nie pojawia (tylko ramka z tekstem alternatywnym; tekst działa dobrze). Mój Content-ID to <filename.jpg>, więc mój href = "cid: filename.jpg" - czy jest jakaś specjalna sztuczka dotycząca wartości lub składni Content-ID i cid:?
— Peter Flynn,

Sprawdziłem z RFC2392 i wyrażenie CID wydaje się być prawidłowe. Ale nadal się nie wyświetla.
— Peter Flynn

Napisałem odpowiedź na podobne pytanie i stworzyłem sztukę ascii, aby wyjaśnić strukturę: stackoverflow.com/a/40420648/633961
— guettli


4

Używanie Base64 do osadzania obrazów w html jest niesamowite. Niemniej jednak proszę zauważyć, że ciągi base64 mogą zwiększyć rozmiar wiadomości e-mail.

W związku z tym,

1) Jeśli masz wiele obrazów, przesłanie ich na serwer i załadowanie tych obrazów z serwera może zmniejszyć rozmiar wiadomości e-mail. (Możesz uzyskać wiele bezpłatnych usług za pośrednictwem Google)

2) Jeśli w twojej poczcie jest tylko kilka obrazków, użycie łańcuchów base64 jest zdecydowanie świetną opcją.

Oprócz opcji dostępnych w istniejących odpowiedziach możesz również użyć polecenia do wygenerowania ciągu base64 w systemie Linux:

base64 test.jpg

Wskazany przez Michaela Böcklinga: identyfikatory URI danych w wiadomościach e-mail nie są obsługiwane w wielu popularnych klientach, takich jak Gmail
— Mendy

3

Wiem, że to stary post, ale obecne odpowiedzi nie uwzględniają faktu, że program Outlook i wielu innych dostawców poczty e-mail nie obsługuje obrazów wbudowanych ani obrazów CID. Najskuteczniejszym sposobem umieszczania obrazów w wiadomościach e-mail jest udostępnianie ich online i umieszczanie linku do nich w wiadomości e-mail. W przypadku małych list e-mailowych publiczna skrzynka referencyjna działa dobrze. Zmniejsza to również rozmiar wiadomości e-mail.


2
  1. Aby obrazy w treści były w pełni zgodne, potrzebujesz 3 granic.

  2. Wszystko trafia do multipart/mixed.

  3. Następnie użyj, multipart/relatedaby zawrzeć swój multipart/alternativei twój obraz załącznika nagłówki.

  4. Na koniec umieść załączniki do pobrania w ostatniej granicy multipart/mixed.


11
Byłoby pomocne, gdybyś dołączył przykład.
— Makyen

7
Jeszcze bardziej przydatne byłoby odniesienie do specyfikacji.
— jbruni

2

W rzeczywistości istnieje bardzo dobry wpis na blogu, który wymienia zalety i wady trzech różnych podejść do tego problemu autorstwa Martyn Davies. Możesz go przeczytać na https://sendgrid.com/blog/embedding-images-emails-facts/ .

Chciałbym dodać czwarte podejście wykorzystujące obrazy tła CSS.

Dodaj

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

do treści wiadomości e-mail i klasy css, takiej jak:

#myImage {
    background-image:  url('data:image/png;base64,iVBOR...[some more encoding]...rkggg==');
    width: [the-actual-image-width];
    height: [the-actual-image-height];
}

2

Dla tych, którzy nie mogli uruchomić jednego z tych rozwiązań: Wyślij obraz w wiadomości e-mail Postępując zgodnie z krokami przedstawionymi w rozwiązaniu oferowanym przez @ T30, udało mi się wyświetlić mój obraz w tekście bez blokowania go przez Outlooka (poprzednie metody były blokowane) . Jeśli korzystasz z wymiany, tak jak my, wtedy również:

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

będziesz musiał przekazać go hostowi adresu URL usługi wymiany. Poza tym, zastosowanie tego rozwiązania powinno umożliwić łatwe wysyłanie osadzonych obrazów.


1

Może być interesujące, że zarówno Outlook, jak i Outlook Express mogą generować te wieloczęściowe formaty wiadomości e-mail, jeśli wstawisz pliki obrazów za pomocą funkcji menu Wstaw / Obraz.

Oczywiście typ wiadomości e-mail musi być ustawiony na HTML (nie jako zwykły tekst).

Każda inna metoda (np. Przeciągnij / upuść lub dowolne wywołanie wiersza poleceń) powoduje wysłanie obrazu (ów) jako załącznika.

Jeśli wyślesz taki e-mail do siebie, zobaczysz, jak jest sformatowany! :)

FWIW, szukam samodzielnego pliku wykonywalnego systemu Windows, który wykonuje obrazy w wierszu z trybu wiersza poleceń, ale wydaje się, że nie ma. To ścieżka, którą przeszło wielu ... Można to zrobić, powiedzmy, Outlook Express, przekazując mu odpowiednio sformatowany plik .eml.


0

Poniżej znajduje się działający kod z dwoma sposobami osiągnięcia tego:

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

Dodatkowa wskazówka do posta Pavela Perny, która bardzo mi pomogła (nie mogę komentować mojej reputacji, dlatego zamieszczam to jako odpowiedź): W niektórych wersjach Microsoft Exchange, dyspozycja zawartości w treści jest usuwana ( zobacz ten post Microsoft ). Obraz po prostu nie jest częścią poczty, którą użytkownik widzi w Outlooku. Aby obejść ten problem, użyj opcji „Dyspozycja zawartości: załącznik”. Outlook 2016 nie wyświetla obrazów jako załączników, które są używane w wiadomości e-mail, chociaż używają one opcji „Dyspozycja treści: załącznik”.


-31

Jeśli używasz programu Outlook do wysyłania statycznego obrazu z hiperłączem, prostym sposobem byłoby użycie programu Word.

  1. Otwórz MS Word
  2. Skopiuj obraz na pustą stronę
  3. Dodaj hiperłącze do obrazu (Ctrl + K)
  4. Skopiuj obraz do wiadomości e-mail
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.