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.

tbone
źródło
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.

Bernd
źródło
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("[email protected]");
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();
Khyati Elhance
źródło
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

Pavel Perna
źródło
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
Brian
źródło
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.

Skuter Crawford
źródło
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.

Steven Newman
źródło
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];
}
GerardV
źródło
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 protected]");
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.

tstrand66
źródło
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.

Piotr
źródło
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 = "[email protected]";
            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("[email protected]");
            recipient.Resolve();

            // Send.
            mailItem.Send();
        }
    }
}
Tarik
źródło
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”.

Klendatho
źródło
-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
Claudio Viz
źródło