26

I am trying to find out the best way to add an image inside the body of the email and not as attachment in ios.

1) Apple has provided a function "addAttachment" and the doc says, to add any image in the content, we should use this function, but I tried that function, and sent an mail, I checked on my browser, it is recieved as an attachment.

2) Secondly, many blogs say to use base64 encoding, but that also wont work, image is sent as a broken one.

So friends, please help me out to find the best available solution to do this.

Regards Ranjit

Ranjit
  • 4,576
  • 11
  • 62
  • 121
  • [Detailed answer is here](http://stackoverflow.com/questions/1527351/how-to-add-an-uiimage-in-mailcomposer-sheet-of-mfmailcomposeviewcontroller-in-ip) – Hemang Jan 16 '13 at 13:19

4 Answers4

62

Set email format as HTML. This code is woking fine in my app.

MFMailComposeViewController *emailDialog = [[MFMailComposeViewController alloc] init];

NSString *htmlMsg = @"<html><body><p>This is your message</p></body></html>";

NSData *jpegData = UIImageJPEGRepresentation(emailImage, 1.0);

NSString *fileName = @"test";
fileName = [fileName stringByAppendingPathExtension:@"jpeg"];
[emailDialog addAttachmentData:jpegData mimeType:@"image/jpeg" fileName:fileName];

emailDialog setSubject:@"email subject"];
[emailDialog setMessageBody:htmlMsg isHTML:YES];


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

Swift 5

import MessageUI

    func composeMail() {

        let mailComposeVC = MFMailComposeViewController()

        mailComposeVC.addAttachmentData(UIImage(named: "emailImage")!.jpegData(compressionQuality: CGFloat(1.0))!, mimeType: "image/jpeg", fileName:  "test.jpeg")

        mailComposeVC.setSubject("Email Subject")

        mailComposeVC.setMessageBody("<html><body><p>This is your message</p></body></html>", isHTML: true)

        self.present(mailComposeVC, animated: true, completion: nil)
    }
Nikita
  • 460
  • 5
  • 11
msk
  • 8,885
  • 6
  • 41
  • 72
  • Hi @MSK , thanks for ur reply, have you checked the received mail in browser, eg, for gmail , yahoo, how does it appear, inside the body of the email or as a attchment? – Ranjit Aug 31 '12 at 07:28
  • 2
    Hi @MSK, I have a doubt, here only u have created the string using HTML and not Image, so how is that going into the body, and suppose if I not create the string using HTML then the image goes as attachment,not very clear to me, could you please explain – Ranjit Aug 31 '12 at 12:52
  • Hi @MSK, could u please look at my doubt – Ranjit Sep 03 '12 at 10:07
  • @Ranjit I am not sure but most likely it is MFMailComposeViewController sending them inline if mail format is HTML (and the content). – msk Sep 03 '12 at 10:59
  • I thought so, but thats strange, and what role the filename plays? – Ranjit Sep 03 '12 at 11:48
  • Filename parameter must not be nil. If you open mail in Mail App on OS X and save the image to disk, the file name is retained. – msk Jan 21 '14 at 18:49
  • Anyone worked out a Swift equivalent? This approach is not working for me in Swift. – Steve N Dec 29 '14 at 14:19
  • This solution does NOT work to insert an image in the message BODY as OP requested. See the below solution by @Richard for Swift or mine below that in Obj-C. – Andrew Nov 02 '15 at 10:12
  • @Andrew try opening the mail in Gmail, Yahoo clients (web, iOS, Android). My experience was that the base 64 encoded embedded image was not rendered in some email clients. Finally we uploaded and used the hosted image in HTML email. – msk Nov 02 '15 at 16:21
  • 1
    The thing is that code provided does not include an image in the email body. The image body is defined as HTML yet the HTML does make reference to the image. So while some mail clients might choose to inline the image attachment entirely on their own, it was not technically in the body of the message. – Andrew Nov 02 '15 at 17:23
11

I just went through this recently for Swift.

Function to add photo to email in Swift:

func postEmail() {
    var mail:MFMailComposeViewController = MFMailComposeViewController()
    mail.mailComposeDelegate = self
    mail.setSubject("your subject here")

    var image = // your image here
    var imageString = returnEmailStringBase64EncodedImage(image)
    var emailBody = "<img src='data:image/png;base64,\(imageString)' width='\(image.size.width)' height='\(image.size.height)'>"

    mail.setMessageBody(emailBody, isHTML:true)

    self.presentViewController(mail, animated: true, completion:nil)
}

Function to return the formatted image:

func returnEmailStringBase64EncodedImage(image:UIImage) -> String {
    let imgData:NSData = UIImagePNGRepresentation(image)!;
    let dataString = imgData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
    return dataString
}
owlswipe
  • 19,159
  • 9
  • 37
  • 82
Richard
  • 1,688
  • 3
  • 16
  • 21
  • 4
    Do these images show up for you correctly in Gmail, Hotmail, etc.? They aren't for me.. – egfconnor Jun 17 '15 at 20:38
  • @Richard, superb solution :-D. – sabiland Oct 01 '15 at 09:56
  • 4
    This works in iOS, but beware - still does not work in hotmail, gmail or for that matter most other clients as egfconnor mentioned. – Jakob Hviid PhD Nov 23 '15 at 14:18
  • @Richard this does not actually work. Picture gets blown up massively and receiver gets image's encoding instead of the picture itself if they use GMail's web client (or others, as egfconnor pointed out). – owlswipe Apr 30 '16 at 14:48
3

I've found that (at least in my case) a PNG will work in the message composer but NOT when the message is opened / received by the user.

Composer Dandily showing logo PNG image!

Viewer Not so much logo images over here.

(Occasionally there will be a light blue outline where the image should be.)

Using the HTML body string below and the conversion below that seems to do the trick.


Message Body HTML String using JPEG

NSString *body = [NSString stringWithFormat:
                  @"\
                  <html>\
                    <body>\
                        Check out the App!\
                        <br>\
                        Isn't this a terriffic logo?!.\
                        <br>\
                        <img src = \"data:image/jpeg;base64,%@\" width = 100 height= 100>\
                        <br>\
                        <a href = \"%@\" > CLICK ITTTTTTT! </a>\
                    </body>\
                  </html>",
                  imageString, @"http://www.LOLamazingappLOL.com"];

Convert Image to string with JPEG Data

+ (NSString *)dataStringFromImage:(UIImage *)image
{
    NSData *imgData = UIImageJPEGRepresentation(image, 1);
    return [imgData base64EncodedStringWithOptions:kNilOptions];
}

Additional Info:

  • iOS Target = 8.0
  • iOS Device = 9.1
  • I am awful with HTML!

Thank you @Richard for the CORRECT answer to this question.

Andrew
  • 1,344
  • 1
  • 12
  • 20
1

Few things to note: - Use addAttachmentData - use setMessageBody and set isHTML:true

you dont have to add manually in your email body. the api will take care of that.

func postEmail() {
var mail:MFMailComposeViewController = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setSubject("your subject here")
var image = // your image here
var imageData = UIImageJPEGRepresentation(image, 1)
mail.addAttachmentData(imageData, mimeType:"image/jpeg", fileName:"Your Filename"
var emailBody = "<html><body><p>This is your message</p></body></html>"
mail.setMessageBody(emailBody, isHTML:true)

self.presentViewController(mail, animated: true, completion:nil)}
Ansyar Hafid
  • 229
  • 3
  • 5