email-attachmentsmfmailcomposeviewcontrollerios9.3

iOS 9.3 Email with attachments never sends


Using the MFMailComposeViewController with attachments causes the email to stay in the Outbox and never get sent from my Air 2. Same app on my Pro with 9.2 sends fine.

//.h

   @interface embEmailData : NSObject
{
    NSArray     *to;
    NSArray     *cc;
    NSArray     *bcc;
    NSString    *subject;
    NSString    *body;
    NSArray     *attachment;
}

@property (nonatomic, assign) BOOL optionsAlert;

-(void)setTo:(NSArray*)to;
-(NSArray*)to;

-(void)setCc:(NSArray*)cc;
-(NSArray*)cc;

-(void)setBcc:(NSArray*)bcc;
-(NSArray*)bcc;

-(void)setSubject:(NSString*)subject;
-(NSString*)subject;

-(void)setBody:(NSString*)body;
-(NSString*)body;

-(void)setAttachment:(NSArray*)attachment;
-(NSArray*)attachment;

-(void)setOptionsAlert:(BOOL)options;

//.m

#import "embEmailData.h"
#import <MessageUI/MFMailComposeViewController.h>
#import "UIImage+Utilities.h"
@import MessageUI;

#define kemailShowNSLogBOOL NO

@interface embEmailData () <MFMessageComposeViewControllerDelegate, MFMailComposeViewControllerDelegate>
@property (nonatomic, strong) embEmailData      *receivedData;
@property (nonatomic, strong) UIViewController  *topVC;
@end

@implementation embEmailData

- (id)init {
    self = [super init];
    if (self) {
        // Delay execution of my block for 0.1 seconds.
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
            [self postEmail];
        });

        _topVC = [UIApplication sharedApplication].keyWindow.rootViewController;

    }
    return self;
}

-(void)setTo:(NSArray*)_to
{
    to = _to;
    if (kemailShowNSLogBOOL) NSLog(@"%@",to);
}

-(NSArray*)to {
    return to;
}

-(void)setCc:(NSArray*)_cc
{
    cc = _cc;
    if (kemailShowNSLogBOOL) NSLog(@"%@",cc);
}

-(NSArray*)cc {
    return cc;
}

-(void)setBcc:(NSArray*)_bcc
{
    bcc = _bcc;
    if (kemailShowNSLogBOOL) NSLog(@"%@",bcc);
}

-(NSArray*)bcc {
    return bcc;
}

-(void)setSubject:(NSString*)_subject
{
    subject = _subject;
    if (kemailShowNSLogBOOL) NSLog(@"%@",subject);
}

-(NSString*)subject {
    return subject;
}

-(void)setBody:(NSString*)_body
{
    body = _body;
    if (kemailShowNSLogBOOL) NSLog(@"%@",body);
}

-(NSString*)body {
    return body;
}

-(void)setAttachment:(NSArray*)_attachment
{
    attachment = _attachment;
    if (kemailShowNSLogBOOL) NSLog(@"%@",attachment);
}

-(NSArray*)attachment {
    return attachment;
}

-(void)setOptionsAlert:(BOOL)options
{
    if (options)
    {
        if (kemailShowNSLogBOOL) NSLog(@"options");
    }
    else
    {
        if (kemailShowNSLogBOOL) NSLog(@"no options");
    }

    _optionsAlert = options;
}

-(void)postEmail
{
    _receivedData = self;
    [self emailData];
}

#pragma mark - Email Delegates
-(void)emailData
{
    if ([MFMailComposeViewController canSendMail] == YES) {

        MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
        picker.mailComposeDelegate = self; // &lt;- very important step if you want feedbacks on what the user did with your email sheet

        if(_receivedData.to)
            [picker setToRecipients:_receivedData.to];

        if(_receivedData.cc)
            for (NSString *email in _receivedData.cc) {
                NSLog(@"cc email: %@",email);
            }
            [picker setCcRecipients:_receivedData.cc];

        if(_receivedData.bcc)
            [picker setBccRecipients:_receivedData.bcc];

        if(_receivedData.subject)
            [picker setSubject:_receivedData.subject];

        if(_receivedData.body)
            [picker setMessageBody:_receivedData.body isHTML:NO]; // depends. Mostly YES, unless you want to send it as plain text (boring)

        // attachment code
        if(_receivedData.attachment) {

            NSString    *filePath;
            NSString    *justFileName;
            NSData      *myData;
            UIImage     *pngImage;
            NSString    *newname;

            for (id file in _receivedData.attachment)
            {
                // check if it is a uiimage and handle
                if ([file isKindOfClass:[UIImage class]]) {
                    NSLog(@"UIImage");

                    myData = UIImagePNGRepresentation(file);
                    [picker addAttachmentData:myData mimeType:@"image/png" fileName:@"image.png"];

                    // might be nsdata for pdf
                } else if ([file isKindOfClass:[NSData class]]) {
                    NSLog(@"pdf");
                    myData = [NSData dataWithData:file];
                    NSString *mimeType;
                    mimeType = @"application/pdf";
                    newname = @"Westbrook Brochure.pdf";
                    [picker addAttachmentData:myData mimeType:mimeType fileName:newname];

                    // it must be another file type?
                } else {

                    justFileName = [[file lastPathComponent] stringByDeletingPathExtension];

                    NSString *mimeType;
                    // Determine the MIME type
                    if ([[file pathExtension] isEqualToString:@"jpg"]) {
                        mimeType = @"image/jpeg";
                    } else if ([[file pathExtension] isEqualToString:@"png"]) {
                        mimeType = @"image/png";
                        pngImage = [UIImage imageNamed:file];
                    } else if ([[file pathExtension] isEqualToString:@"doc"]) {
                        mimeType = @"application/msword";
                    } else if ([[file pathExtension] isEqualToString:@"ppt"]) {
                        mimeType = @"application/vnd.ms-powerpoint";
                    } else if ([[file pathExtension] isEqualToString:@"html"]) {
                        mimeType = @"text/html";
                    } else if ([[file pathExtension] isEqualToString:@"pdf"]) {
                        mimeType = @"application/pdf";
                    } else if ([[file pathExtension] isEqualToString:@"com"]) {
                        mimeType = @"text/plain";
                    }

                    filePath= [[NSBundle mainBundle] pathForResource:justFileName ofType:[file pathExtension]];
                    NSLog(@"filePath %@ ",filePath);

                    UIImage * thumb = [UIImage imageNamed:filePath];
                    UIImage * resizeThumb = [UIImage resizeImage:thumb withMaxDimension:999];

                    if ([[file pathExtension] isEqualToString:@"pdf"]) {

                        //myData = [NSData dataWithData:file];
                        myData = [[NSFileManager defaultManager] contentsAtPath:filePath];
                        NSLog(@"ITS A PDF");
                    } else // if it is anything but a png file

                        if (![[file pathExtension] isEqualToString:@"png"]) {
                            //myData = [NSData dataWithContentsOfFile:filePath];
                            myData = UIImageJPEGRepresentation(resizeThumb, 1.0);

                        } else {
                            myData = UIImagePNGRepresentation(resizeThumb);
                        }

                    newname = file;
                    [picker addAttachmentData:myData mimeType:mimeType fileName:newname];

                }
            }
        }

        picker.navigationBar.barStyle = UIBarStyleBlack; // choose your style, unfortunately, Translucent colors behave quirky.
        [_topVC presentViewController:picker animated:YES completion:nil];

    } else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Status" message:[NSString stringWithFormat:@"Email needs to be configured before this device can send email. \n\n Use support@neoscape.com on a device capable of sending email."]
                                                       delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
        [alert show];
    }
}

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
    // Notifies users about errors associated with the interface
    switch (result)
    {
        case MFMailComposeResultCancelled:
            break;
        case MFMailComposeResultSaved:
            break;
        case MFMailComposeResultSent:
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Thank you!" message:@"Email Sent Successfully"
                                                           delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
            [alert show];
        }
            break;
        case MFMailComposeResultFailed:
            break;

        default:
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Status" message:@"Sending Failed - Unknown Error"
                                                           delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
            [alert show];
        }
            break;
    }
    [_topVC dismissViewControllerAnimated:YES completion:nil];
}

-(void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
    NSLog(@"FINISHED");
}

Solution

  • EDIT: It still sometimes randomly does this for me. They sit in Outbox until I delete them. I updated to 9.3.5 and the emails sent. Unsure of what is going on.

    I went to delete my email account from my device (which is a corporate Gmail account). I noted that Mail, Calendar, Contacts and Notes were ON.

    After deleting and adding in again Notes defaulted to OFF and my email can now send from my apps again. YMMV.