How to add a UIImage in MailComposer Sheet of MFMailComposeViewController
Asked Answered
H

8

53

I want to insert a UIImages inside the compose sheet of an MFMailComposerViewController.

Please note I don't want to attach them, but I want to place them in a table using HTML code which will be the part of the email body.

Hurwitz answered 6/10, 2009 at 18:44 Comment(2)
Have you had any luck with this more recently by any chance? I'm working on the same problem and too am facing the same issue.Photoconduction
see #12211071Coolish
B
64

Back again with a new answer. I'm still leaving my previous code up though, because I'm still not convinced that there's not a way to make use of it. I'll keep at it myself. The following code DOES work. Mustafa suggests base64 encoding the images, and says that they only work Apple to Apple, but that's not actually true. Base64 encoding does work with most mail clients now (IE previously didn't support it, but now it is supported for images up to a certain size, though I'm not sure exactly what the size is). The problem is that mail clients like Gmail would strip out your image data, but there's a simple workaround for that... just putting <b> and </b> tags around your <img ...> tag is all you need to do to keep it from getting stripped out. In order to get an image into your email, you need to get a base64 encoder into your project. There are several out there (mostly C though), but the simplest ObjC one I found was called NSData+Base64 by Matt Gallagher (I took the "+" out of the name after copying it in because it gave me problems). Copy the .h and .m files into your project and be sure to #import the .h file where you plan on using it. Then code like this will get an image into your email body...

- (void)createEmail {
//Create a string with HTML formatting for the email body
    NSMutableString *emailBody = [[[NSMutableString alloc] initWithString:@"<html><body>"] retain];
 //Add some text to it however you want
    [emailBody appendString:@"<p>Some email body text can go here</p>"];
 //Pick an image to insert
 //This example would come from the main bundle, but your source can be elsewhere
    UIImage *emailImage = [UIImage imageNamed:@"myImageName.png"];
 //Convert the image into data
    NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(emailImage)];
 //Create a base64 string representation of the data using NSData+Base64
    NSString *base64String = [imageData base64EncodedString];
 //Add the encoded string to the emailBody string
 //Don't forget the "<b>" tags are required, the "<p>" tags are optional
    [emailBody appendString:[NSString stringWithFormat:@"<p><b><img src='data:image/png;base64,%@'></b></p>",base64String]];
 //You could repeat here with more text or images, otherwise
 //close the HTML formatting
    [emailBody appendString:@"</body></html>"];
    NSLog(@"%@",emailBody);

 //Create the mail composer window
    MFMailComposeViewController *emailDialog = [[MFMailComposeViewController alloc] init];
    emailDialog.mailComposeDelegate = self;
    [emailDialog setSubject:@"My Inline Image Document"];
    [emailDialog setMessageBody:emailBody isHTML:YES];

    [self presentModalViewController:emailDialog animated:YES];
    [emailDialog release];
    [emailBody release];
}

I've tested this on the iPhone and sent lovely image embedded emails to myself on Yahoo, my personal website, and my MobileMe. I don't have a Gmail account, but the Yahoo worked perfectly, and every source I've found says that the bold-tags are all you need to make it work. Hope this helps all!

Breath answered 17/3, 2010 at 10:30 Comment(6)
Have you tested this recently with gmail? I seem to only get a bunch of text instead of the image.Grandson
The <b></b> trick no longer appears to work. No matter what I do Gmail wont display the image. Desktop client work fine.Tripper
[[[NSMutableString alloc] initWithString:@"<html><body>"] retain]: alloc already does a retain, so you are retaining too muchTragedy
Here's just an update on the matter. This approach is NOT working for me with Gmail, Yahoo, or Hotmail. The embedded base 64 encoded images are not displayed. But, Map.app is showing the embedded images (Mac and iOS), but it isn't good enough.Definitive
This also doesn't render correctly with Gmail on Android, Outlook, or Zimbra.Klinges
Confirmed: very good and easy to implement idea.. But not working with most of the famous emails servers.. Too bad :(Facer
D
11

There are two ways to do this, depending on where the images are stored:

If the images are out on a server, then just include HTML <img> tags with the source URL set to the remote image. The user previewing the mail message is shown the image during composition and the receiver sees it when they open the message (unless they've disabled default image loading).

If the images are on the phone you could include them as 'inline' images. There are two steps to this. First you have to attach all the images you want to use as multi-part MIME attachments and they will need to be assigned a 'content ID' (aka cid), a filename, and Content-Disposition set to inline. Inside your HTML message body you can reference them like so:

<img src="cid:{messageid}/image.png" alt="My image" />

The bad news is, the standard iPhone mail composer mechanism doesn't allow adding this additional data to attachments. The second thing is to mark the email as having an "alternative" MIME content-type. Again, the mail composer doesn't let you do that.

The way around this is to either compose the message yourself then send it off to the mail server directly via SMTP, or have a server proxy do it for you via an SMTP relay. If you decide to go this way you might want to check out skpsmtpmessage on Google code or a service like AuthSMTP.

Once the user receives this message, however, they see a self-contained HTML message with all the inline images right there. But it's a lot of hassle to set up. The first method (putting images on server) is by far the easier way to go.

Dorweiler answered 6/10, 2009 at 20:9 Comment(1)
So you just can directly insert the UIImages stored in iPhone database. You either need to store them on server or create the message on ur own and send it.Hurwitz
C
4

For iOS 3.0 and later, please see this: Attaching an image to an email?

Example:

UIImage * image = [UIImage imageWithContentsOfFile:imagePath];
[composer addAttachmentData:UIImageJPEGRepresentation(itemImage, 1) mimeType:@"image/jpeg" fileName:@"MyFile.jpeg"];
Captive answered 15/3, 2011 at 3:21 Comment(0)
D
1

Maybe this'll work for you:

How to Embedd UIImage into a Mail Composer message body

Here's what it says:

Basically, you convert your image to base64 (the base64 attached below have to be shorten cause of the message length limit, so it's not a valid image) string and embed in the image tag. I remember I've stop working on this is because the embedded image(s) are only viewable from iPhone to another iPhone, I remember testing it with Gmail, our work Outlook client with no luck display the image, when I view source the data is there. So I don't think is the so much of a spam filter issue but email clients are just smarter. While I was research this, I actually found that this is how many spammers to blast out emails with image only info so it by passes the spam filter. Damn spammers, I was going to use it for good cause but since it was pretty much useless when I found out that most mail client won't display the image. For what it's worth, here is the code.

NSString *eMailBody = @"<html>Just convert your image file to base64 to embed into the email<img src="data:image/gif;base64,R0lGODlhFAFuAPcAAPf39//7/+fn59bT1u/r787Lzq0UAN7b3hhFrRhJtRA0hBA8lMYYALWytffz94wQAMa+vb26vRhNxufj5+/v78bDxvfz772+vcbHxghRCM7PzggkYyFZ1tYkCNbX1hhRzpyenO+6AN7f3gBlANauAGOW7zFl1kp95wg8pbW2tZyanHOi797f5zlx3msMAAB9CP/PAL22va2mraWipedJMSlRtf91Y72WAFqK76WmpRBFta2qrcaeAK2urfdpUuc8If39/e9ZQmPTY94wGFrLWrUkEISq9/n5+ZR5ABCWGLWOAIRpAGNRAClJlK2GAL0sGGssITG2OaWCAK3H9848KaW+762qpcbX/73jvWN5pGvTc/eGc//vCFppfIwgEJRBMYSGlPeWhJSSjHN5jMaSjKWmrb3P787V1ilBa4R9c9nXy+rq6ntNQu/y95Su3svO1kphlISa1t7b1vf7/3uGraWGexdAmoySlDm6QrWyraWqrRiiIWtpa0LDStrl/1JtrcbHzpxlWntlUklVcztZk3vbhISStfffWufr786upVmB1ta2taW21tLS0ve6rd7j5zlhtfemnJSetefn78LCw7W2vdnZ2bVFMf/3//f3/8Z1a9bb59bb3eHh4a2WjM7HxoR1OSGqKbW6xvT09JyGQrXD3v/r5+fk3s7rzufb3q2ytffXKbWiY6inp1p1WrWmjP/LxnOOzsC/v+/n56qSMffXzr2eEP/3hPHx8f//987T57m4ubVZShk5f97LjO/HKQ03ks7DpdZlWv/vMd7LxqWuvefr/86uKd66QgwyhcnJyf/ztbKxsrWqpe/37//z7///75zTpf/397Szsvfn1ozLjO/jlN7v3qWko62OEO/r5//73tbX3vf37wotd1qqYxlNvYyujN7X1qKgoHuWe5KUmkKOQhZKvildMRh5IZqZmcXEwZ2amaajoNfU0QMaTAsiV5STlSo+bZibpSti2puZl5u28pGs5pqbn9Hd8/fr94WFi7i1sBguYfP09v///ywAAAAAFAFuAAAI/wD/CRxIsKDBgwgTKlzIsKHDhxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqXLlzBjypxJs6bNmzhz6tzJs6fPn0CDCh1KtKjRo0iDYinEtJAWLUSIfJv6DVFShnOMXTEzpYrXKlPMXDGW6apZhli0CHmqtk+oJC9ejDDH6azBTGaMKDLBQUKCvzoC/5XAwcSJElV0UbB71lk0PFH6CGmqxS3cuZgyAwhw1tiUEiY+CEZBunTpwR9SfyisiNGmzYyNYqlWLZrtak6JRLmcoQKBCQQswEZ6ZcUJDn0RoFiwoAkhOH/+wCHURDkKHRIII0e+uoWbSbGRYv/SFy0qnj1yM6ArUEDDAQEOOBu9UqIF3xrMCWWRBGiAnP8eqKEBBpVIkgUhyg22nWocxKJLeEMBYIEAqVSD"></html>";

NSString *encodedBody = [eMailBody stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *urlString = [NSString stringWithFormat:@"mailto:[email protected]?subject=ImageTest&body=%@", encodedBody];
NSURL *url = [[NSURL alloc] initWithString:urlString];
[[UIApplication sharedApplication] openURL:url];
Definitive answered 18/1, 2010 at 14:8 Comment(0)
B
1

(Unfortunately the following method doesn't work, but I'm leaving this post because the image URL path conversion string example is really helpful for other cases where you need HTML filepaths in your code. Please see my post on Base64Encoding for a way that does work.)

I ran into this issue myself, and I found a way that works. You CAN get the images to appear inline by using the full filepath to the image.

It takes a little conversion on your part, but use the normal methods for obtaining your app's directories (NSString *path = [[NSBundle mainBundle] resourcePath], etc...), then convert the string to a literal URL. For example, the "path" string returned above will contain something like "/Users/Me/Library/Application Support/iPhone Simulator/3.2/Applications/25ADA98D-8DF4-4344-8B78-C18BC757EBDC/MyEmailingApplication.app".

You'll need to make this string into

"file:///Users//Me//Library//Application%20Support//iPhone%20 Simulator//3.2//Applications//25ADA98D-8DF4-4344-8B78-C18BC757EBDC//MyEmailingApplication.app//"

and then you can add your image filenames to the end. (this example points into the app resources, but the same applies for the tmp and documents directories).

You can do this string conversion with a combination of [NSString stringWithFormat:@"file:///%@//%@",path,myImageName]

after using [path stringByReplacingOccurencesOfString:@"/" withString:@"//"]

to fix the forward-slashes in "path", and

[path stringByReplacingOccurencesOfString:@" " withString:@"%20"]

to make the spaces HTML friendly. Now you can use this literal URL in your HTML encoded email body, like img src=\"",pathToMyImage,"\"

The example looks like a lot of work, but actually once you get it setup, it's not hard at all, and it works like a charm :-) Good luck!

Breath answered 10/3, 2010 at 6:8 Comment(2)
Crap! Check the full code I posted below. It doesn't work when actually sent from the device. It looks perfect in the composition window (images showing inline and everything), but the actual sent email doesn't include the images or the code embedding them :-( I'm leaving this posted in the meantime while I check it out in case it gets us on the right track.Breath
It works in the composition window because you're referring to the local file location directly. So when you send it, the reference is still the same (to your local file location). So that's why it doesn't work. Because the file no longer exists.Tiresome
F
0

I tried the Mike's answer works perfect inside the MFMailComposerViewController, but unfortunately not with most of the emails clients. Since I really need to send some email content with UIImage embedded, here's what I've done:

  1. I kept the Mike's answer code to generate my HTML page with UIImage
  2. I've created an UIWebView presenting this page, with [yourwebview loadHTMLString:@"yourHTMLString" baseURL:nil]
  3. IMPORTANT: I display this in an UIViewController as a Preview page for the user
  4. Then I generate a PDF from this UIWebView, thanks to AnderCover's method
  5. Finally, I add the created PDF as an attachement to the email with [mailComposerController addAttachmentData:yourPDFFileAsNSData mimeType:@"application/pdf" fileName:@"yourFileName.pdf"]

Ok, don't blame me, I know this is a lot of conversions and actions for just adding some images, but your HTML email structure remains the same with images embedded, and the final user will receive only one good-looking attachement.
The "dirty" part is that the PDF content is actually screenshots of the webview...Not really reusable.

Facer answered 27/8, 2014 at 14:57 Comment(0)
B
-1

EDIT: What you're about to read DOESN'T work (yet)! Check my other post on Base64 Encoding your image which DOES work.

This one looks just fine in the email composition window, but the actual sent email doesn't include the pics (I just tested it on my phone). I mistakenly thought that the mail app would base64 encode the images itself (It does so for attached images). And, although it's a pain, you can get an email on the iPhone to insert multiple "flowed" inline images by going to your image folder, copying an image to the clipboard, going to your email, and pasting it where you want. You can write more text, save the email as a draft, and repeat the process with more images pasted into the same email. Send the email to yourself, then open it on your computer with Text Edit. You'll be able to see exactly the formatting that the email takes (including the base64 encoded images).

What strangely happens with my code below is that the text makes it into the email, but the images just disappear entirely (not even a dangling "broken" reference to them :-/ ). This makes me doubt that linking to the images on an external server would work. I'm going to continue working on this... I'm wondering if it will behave differently if I have the email launch in the mail app outside of my program. I'll keep coming back to update this as I figure more out... it just seems like this should be easier than Apple makes it :-/

This code is written for image files that you'd store in your "Documents" directory (so your app would have to be creating images that are stored there, and HTML code that references those images. For images that you have stored in the app bundle, use [[NSBundle mainBundle] resourcePath] for the initial path to the images).

- (void)createEmailWithInlineImages {
//get app Documents directory
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsPath = [paths objectAtIndex:0];
//make spaces HTML friendly
    documentsPath = [documentsPath stringByReplacingOccurrencesOfString:@" " withString:@"%20"];
//make forward-slash into double-forward-slash for HTML file-URL comapatibility
    documentsPath = [documentsPath stringByReplacingOccurrencesOfString:@"/" withString:@"//"];
//get the name for your image into the string however your app works
//create a string formatted like a literal HTML URL to the image, e.g.
//file:///myiPhoneFileSystemPath//MyApplication//MyApplicationDirectories//Documents//imageName.jpg
    NSString *myHTMLImageName = @"myHTMLImage.jpg";
    NSString *imagePath = [NSString stringWithFormat:@"file:///%@//%@",documentsPath,myHTMLImageName];

//this string is an example of your email body text with HTML formatting
    NSString *emailText = [NSString stringWithFormat:@"%@%@%@",@"<html><head><title>My Inline Image Example Email</title></head><body><p>Here's some text before the inline image</p><p><img src = \"",imagePath,@"\"></p><p>Here's some text for after the inline image. You could add more inline images and text after this with the same kind of formatting.</p></body></html>"];

//create email
    MFMailComposeViewController *emailDialog = [[MFMailComposeViewController alloc] init];
    emailDialog.mailComposeDelegate = self;
    [emailDialog setSubject:@"My Inline Image Email Document"];

    [emailDialog setMessageBody:emailText isHTML:YES];

    [self presentModalViewController:emailDialog animated:YES];
    [emailDialog release];
}
Breath answered 11/3, 2010 at 10:37 Comment(2)
BTW, thanks to Ramin for initially mentioning that images stored on a server would work. That gave me the idea to try for literal URLs within the iPhone file system :-)Breath
If you didn't see my note above, check my new post RE:Base64Encoding your image. It works really well for most cases.Breath
B
-1
  1. remove the image tag
  2. just take the removed image tag and display using uimage view

I tried the above examples, but they are not working. Below you will find sample code that works 100%. But you need to check the image tag url.

//remove  the img tag 

NSScanner *theScanner;
NSString *gt =nil;

theScanner = [NSScanner scannerWithString:emailBody];

while ([theScanner isAtEnd] == NO) {

    // find start of tag
    [theScanner scanUpToString:@"<img" intoString:NULL] ; 

    // find end of tag
    [theScanner scanUpToString:@">" intoString:&gt] ;


    emailBody = [emailBody stringByReplacingOccurrencesOfString:[ NSString stringWithFormat:@"%@>", gt] withString:@""];
    NSString *tt=[ NSString stringWithFormat:@"%@>", gt];
        NSLog(@"*********************%@",tt);
    st=tt;
        NSLog(@"*********************%@",st);
}
st =[st stringByReplacingOccurrencesOfString:@"<img src=\"" withString:@""];
st =[st stringByReplacingOccurrencesOfString:@"\"/>" withString:@""];
st =[st stringByReplacingOccurrencesOfString:@".png" withString:@""];
st =[st stringByReplacingOccurrencesOfString:@"\"align=\"left" withString:@""];
//"align="left
NSLog(@"*********************%@",st);



NSString *path1 = [[NSBundle mainBundle] pathForResource:[ NSString stringWithFormat:@"%@", st] ofType:@"png"];
NSData *myData1 = [NSData dataWithContentsOfFile:path1];
[picker addAttachmentData:myData1 mimeType:@"image/png" fileName:[ NSString stringWithFormat:@"%@", st]];
Bergstein answered 15/3, 2011 at 9:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.