I have a strange problem.
I need to send an e-mail from an MVC site. I have an html template for the email, which looks like this(the image part):
...
<img class="auto-style4" src="{PictureSrc}" /><br />
<img src="data:image/png;base64,{pictureBase64}">
....
From the controller I'm replacing the parameters like this:
case "PictureSrc":
string imagePath = "";
imagePath = "~/Images/email-logo.png";
//string base64 = Convert.ToBase64String(System.IO.File.ReadAllBytes(HttpContext.Server.MapPath(imagePath)));
//content = content.Replace("{pictureBase64}", base64);
content = content.Replace("{" + property + "}", HttpContext.Server.MapPath(imagePath));
break;
1.First I have tried to add the path for the image. This way works on my local machine, but not on the server where the live site is.
I've tried to add the URL for the image. WhenI have pasted the URL in to the browser, the image was shown, but in the sent email the image was not shown, not in my local machine, not on the server.
The interesting thing is that I'm sending these mails to outlook accounts. There the images are not shown, but if I send the mail to my yahoo account there the image is shown.
I've tried to convert image to base 64, as you can see on the code and replacing this way the image src. This way again the image was not shown, not on my local machine, not on the server side if I send the mail to outlook accounts. If I send the mail to a yahoo account, the mail is shown.
Can you please advise what can I try in order to resolve this problem?
I ran into this same issue with Outlook a few months ago. While researching, I learned that Outlook tends to strip emails of embedded images. I resolved it by using the CID technique. This technique consists of attaching the image to the email and referencing it in the email template with the image's CID.
First, you would need to get your image's CID. There are plenty of CID converters online to do this. Then, you just need to use the CID in the img src attribute of your template: <img src="cid:" + yourCID + "/>".
Note: this WILL increase the size of your email due to the image being attached.
Related
I would like to create a ticket with inline image but cannot get through it. I am using a rich text having a pasted screen capture image, the content is like
"<img ..."
By using ZendeskApi_V2, I set the Ticket's Comment HtmlBody with the content mentioned but did not work, neither of PlainBody or Body.
Anyone can help, please.
For instance:
In my application, an image is inserted into a RadEditor
By setting the Ticket.Comment as
var ticket = new Ticket {
Comment = new Comment {
HtmlBody = HttpUtility.HtmlDecode(RadEditor.Content)
}
}
After sending the Create Ticket request, I cannot see the inline image in the Zendesk dashboard.
So, did I do it in a right way? How should an embedded or inline image be sent through Zendesk API?
You may need to upload the attachment file first, then you can set the attachment's token in the comment. See here - https://developer.zendesk.com/rest_api/docs/support/tickets#attaching-files
So I have tried 2 different approaches to creating an inline image using c#:
Using an AlternateView
Using an inline Attachement
Option 2 is worse in that it does not appear inline on any of my test clients (outlook 2010/2013, Samsung android email client, ios 10 email client).
Option 1 is almost perfect, all clients display the inline image correctly as long as there are no other attachments. However, if you add a file attachment to the email, only on the iOS email app you get a strange side effect. On iOS, the client displays both the inline image and the attachment as attachments (the inline image is shown as an icon).
I have tried to figure this out by composing an email in Outlook with an embedded image and an attachment. Outlook generates what looks to be two regular attachments (looking at the raw message data from both Outlook and dotNet generated emails), with the image being marked as content-disposition inline. And this works on all my test clients. Except when using the .Net Mail message api to replicate this (option 2), it doesn't work. I am at a loss to understand what is going on here.
Edit 1
What's interesting is that when using Option 2, the email body is delivered encoded as base64. This is different than how the Outlook client manages to do it. There the body is in plain text and the inline attachment image is the only thing encoded in bas64.
Edit 2
Setting the following properties when using Option 2 returns the body to being plain text again:
mail.BodyEncoding = Encoding.UTF8;
mail.BodyTransferEncoding = TransferEncoding.QuotedPrintable;
So to get this to work I had to combine both approaches. Below is what worked for me, it displays the signature image as intended (inline/embedded) image and the attachment as an icon (in iOS anyway). This also displayed correctly on a Samsung Android phone and in outlook 2010/2013. For the sake of simplicity, I will only include the embedded image in the mail body as an example:
var smtpMail = new SmtpClient
using (var mail = new MailMessage())
{
mail.From = new MailAddress(Settings.Default.FromAddress, Settings.Default.FromDisplayName);
mail.To.Add(toAddress);
mail.Subject = subjectText;
mail.IsBodyHtml = true;
mail.BodyEncoding = Encoding.UTF8;
mail.BodyTransferEncoding = TransferEncoding.QuotedPrintable;
mail.Attachments.Add(new Attachment(nonInlinefilePath));
var imgCid = "img001.jpg"
var bodyText = $"<html><body><img src=\"cid:{imgCid}\" alt=\"Sample Image\" /></body></html>";
var altView = AlternateView.CreateAlternateViewFromString(bodyText, Encoding.UTF8, MediaTypeNames.Text.Html);
var inlineFileResource = new LinkedResource(imagePath, MediaTypeNames.Image.Jpeg)
{
TransferEncoding = TransferEncoding.Base64,
ContentId = imgCid,
ContentType =
{
Name = imgCid
},
};
var inlineFileAttachment = new Attachment(imagePath, MediaTypeNames.Image.Jpeg)
{
ContentId = imgCid
};
inlineFileAttachment.ContentDisposition.Inline = true;
inlineFileAttachment.ContentDisposition.DispositionType = DispositionTypeNames.Inline;
altView.LinkedResources.Add(inlineFileResource);
mail.AlternateViews.Add(altView);
mail.Attachments.Add(inlineFileAttachment);
smtpMail.Send(mail);
}
I don't know enough about either email protocols or the iOS email app to know why this is necessary, but after many, many, many different attempts to get iOS mail app to display this properly, this combo was the only one that worked.
I had a similar issue with a work project. Images embedded in the message body using System.Net.Mail LinkedResource, would appear fine in most email clients, but not with iOS emails after a version upgrade during version 10.
The images would have zero bytes and added attachments with zero size. What I did was to fix this was to define the media type, whereas before I didn't.
Before:
LinkedResource logo = new LinkedResource(HttpContext.Current.Server.MapPath("/images/imgname.png"));
After:
LinkedResource(HttpContext.Current.Server.MapPath("/images/imgname.png"), "image/png");
as a possible alternative you could try base64 encoding your image.
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAADSCAMAAABThmYtAAAAXVB" alt="img" />
I just tested my image in Outlook, outlook for web, and iOS Mail. worked in all for me.
you could use this tool (or any base64 encoder) to generate a base64 image tag
more info here.
another good source of info on this subject
I'm currently working on the imap class by barbushin. It's the only php class over the internet I can find regardless to any encoding issue. Thanks to the coder.
I have a list of messages in a table. Each message sending a message id as GET (say $mid). When a link clicked, the page turned into a view page. It should open that message and display the relevant content right? But it is not. Every message has the same content (the 1st content). The code is designed for gmail but I use it for my client. And it's work.
This is a code:
require_once('../ImapMailbox.php');
define('EMAIL', 'my#domain.com');
define('PASSWORD', '*********');
define('ATTACHMENTS_DIR', dirname(__FILE__) . '/attachments');
$mailbox = new ImapMailbox('{imap.gmail.com:993/imap/ssl}INBOX', EMAIL, PASSWORD, ATTACHMENTS_DIR, 'utf-8');
$mails = array();
// Get some mail
$mailsIds = $mailbox->searchMailBox('ALL');
if(!$mailsIds) {
die('Mailbox is empty');
}
$mailId = reset($mailsIds);
$mail = $mailbox->getMail($mailId);
var_dump($mail);
var_dump($mail->getAttachments());
The original is here: https://github.com/barbushin/php-imap
Finally, I found my way home. According to the script there's a line says "mailId". Which is straight forward what is it about.
It was set to the first array by reset(). So the only thing I need to do is extract the message id from it ($mailId is an array of ids). So I simply add an array behind it.
$mailId=$mailsIds[$_GET[uid]];
While $_GET[uid] is a message id sent from a previous page.
Is there any way of building a profile image url with user id or screen name? I store user ids in database but i don't want to store profile image url.
edit:
I don't want to make a api call too. I want to put user_id inside a url like
<img src="https://twitter.com/users/profile_pic?user_id=123"> Is there a url to do this?
With API 1.1 you can achieve this using these URLs:
https://twitter.com/[screen_name]/profile_image?size=mini
https://twitter.com/[screen_name]/profile_image?size=normal
https://twitter.com/[screen_name]/profile_image?size=bigger
https://twitter.com/[screen_name]/profile_image?size=original
Official twitter documentation Profile Images and Banners
Example
https://twitter.com/TwitterEng/profile_image?size=original
will redirect to
https://pbs.twimg.com/profile_images/875168599299637248/84CkAq6s.jpg
As of June 2020, both the accepted answer and avatars.io no longer work. Here are two alternatives:
unavatar.io
(formerly unavatar.now.sh)
Unavatar can get pictures from quite a few different places including Twitter. Replace [screen_name] in the URL below with the Twitter username you want.
<img src="https://unavatar.io/twitter/[screen_name]" />
For example:
<img src="https://unavatar.io/twitter/jack" width="100" height"100" />
If the demo above ever stops working, it's probably because unavatar.io is no longer available.
Unavatar is open source though, so if it does go down, you can deploy it yourself from the GitHub repo — it even has "Deploy to Vercel/Heroku" buttons. The code to fetch Twitter avatars specifically is here, so you could also use that as part of your own backend.
twivatar.glitch.me
⚠️ As of July 2021 this option no longer works, see the one above instead!
If you want an alternative, you can also use twivatar.glitch.me. Replace [screen_name] in the URL below with the Twitter username you want.
<img src="https://twivatar.glitch.me/[screen_name]" />
For example:
<img src="https://twivatar.glitch.me/jack" width="100" height"100" />
If the demo above ever stops working, it's probably because twivatar.glitch.me is no longer available.
By the way, I didn't build either of these services, they were both made by other people.
Introducing the easiest way to get a Twitter Profile Image without using the Twitter API:
Using http://avatars.io/
As #AlexB, #jfred says, it doesn't work at all on mobile devices.
And it's quite a hard way to get a redirected URL using common frameworks like PHP or JavaScript in your single page.
Simply call http://avatars.io/twitter/ruucm at your image tag, like
<img src="https://avatars.io/twitter/ruucm" alt="twt_profile" border="0" width="259"/>
I've tested it with Angular 2+ and it works without any problem.
As of February 20, 2020 it would appear this is impossible. Using the API seems like the only option at the moment. For more info see my question I've opened here: Twitter profile picture images now blocked on most domains
Based on the answer by #Cristiana214
The following PHP snippet can be used to make the https://twitter.com/[screen_name]/profile_image?size=normal trick work on mobile.
Due to twitters redirect to the mobile version of the site links such as https://twitter.com/[screen_name]/profile_image?size=normal get broken on mobile devices
So the script gets the redirect response (to the user avatar) extracts the address then redirects the page itself
if (!isset($_GET['id'])) $_GET['id'] = 'twitter';
$urlget = curl_init();
curl_setopt($urlget, CURLOPT_URL, 'https://twitter.com/' . $_GET['id'] . '/profile_image?size=normal');
curl_setopt($urlget, CURLOPT_HEADER, true);
curl_setopt($urlget, CURLOPT_RETURNTRANSFER, 1);
$res = curl_exec($urlget);
preg_match_all("/location: (.*)/", $res, $found);
header('Location: ' . $found[1][0]);
So this could be accesses as twitteravatar.php?id=twitter which (at time of writing) reloads to https://pbs.twimg.com/profile_images/767879603977191425/29zfZY6I_normal.jpg
Not pretty but works.
You can get it using the users/show method of the Twitter API -- it does exactly what you described. You give it a the ID or the screen name, and it returns a bunch of data, including profile_image_url.
I found such a solution with C#:
public string Text_toTextFinder(string text, string Fromhere, string Here)
{
int start = text.IndexOf(Fromhere) + Fromhere.Length;
int finish = text.IndexOf(Here, start);
return text.Substring(start, finish - start);
}
string getPhotoURL(string UserName, string size ="x96")
{
using (WebClient client = new WebClient())
{
client.Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2";
string htmlCode = client.DownloadString("https://twitter.com/" + UserName);
return Text_toTextFinder(Text_toTextFinder(htmlCode, "<td class=\"avatar\">", "</td>"), "src=\"", "\"").Replace("normal",size);
}
}
For use:
MessageBox.Show(getPhotoURL("screen_name")); //size = 96x96
MessageBox.Show(getPhotoURL("screen_name","normal"));
MessageBox.Show(getPhotoURL("screen_name","200x200"));
MessageBox.Show(getPhotoURL("screen_name","400x400"));
There is no way to do that. In fact Twitter doesn't provide a url to do that like facebook does ( https://graph.facebook.com//?fields=picture)
The issue is report but the status is: 'WontFix', take a look:
https://code.google.com/p/twitter-api/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Stars%20Type%20Bug%20Status%20Summary%20Opened%20Modified%20Component&groupby=&sort=&id=242#makechanges
Well I'm using a tricky way via PHP Dom Parser
include('simple_html_dom.php');
$html = file_get_html('http://twitter.com/mnckry');
$img = array();
foreach($html->find('img.size73') as $e)
$img[] = $e->src;
foreach($html->find('.profile-header-inner') as $e)
$img[] = str_replace("')", "", str_replace("url('", "", $e->{'data-background-image'}));
echo $img[0];//Avatar
echo "<br>";
echo end($img);//ProfileBG
This will give you something like this;
https://pbs.twimg.com/profile_images/378800000487958092/e04a191de329fcf8d000ca03073ad594_bigger.png
to get 2 other size; for big version remove, "_bigger" for smaller version replace "_bigger" with "_normal"
With version 1.1, use
http://a0.twimg.com/profile_images/XXXXX/afpecvf41m8f0juql78p_normal.png
where XXXXX is the User Id
I'm using the following code to embed images into my MailMessage. What I'm trying to do is embed documents (pdf or docx) into the email.
I've tried hyperlink with a link to href="cdi:myDoc.pdf" but that doesn't work. I've also tried using MailMessage.Attachments.Add() but adds the documents in the attachments section instead of embeding the document in the message.
Anyone how to embed a document in the mailmessage? I know Outlook is able to place the attachments in the body of the message but I can't figure how to do it through mailMessage.
Thanks Susan
Sub MultiPartMime()
Dim mail As New MailMessage()
mail.From = New MailAddress("me#mycompany.com")
mail.To.Add("you#yourcompany.com")
mail.Subject = "This is an email"
Dim htmlView As AlternateView = AlternateView.CreateAlternateViewFromString("<b>this is bold text, and viewable by <img src=""cdi:companylogo""> those mail clients that support html</b>", Nothing, "text/html")
LinkedResource logo = new LinkedResource( "c:\temp\logo.gif" )
logo.ContentId = "companylogo"
htmlView.LinkedResources.Add(logo)
mail.AlternateViews.Add(htmlView)
'send the message
Dim smtp As New SmtpClient("127.0.0.1") 'specify the mail server address
smtp.Send(mail)
End Sub 'MultiPartMime
Try using cid: instead of cdi:. That is one error that comes to mind.
try to use
href="cid:companylogo
(with "cid" instead of "cdi" Like Jakob Mygind suggested) and set it to the contentId that you specified for the LinkedResource.
Also when setting the path to the file, it is good to use the HostingEnvironment.MapPath() method (which is the same of Url.Content() of web projects. It would go with something something like:
LinkedResource logo = new LinkedResource(HostingEnvironment.MapPath("c:\temp\logo.gif"));
Hope it helps!
;)