Friday, January 25, 2013

Sending e-mail in background from iOS apps using SMTP gmail account

The iOS SDK has made it really easy to send email using the built-in APIs. With a few line of codes, you can launch the same email interface as the stock Mail app that lets you compose an email. You can pop up mail composer form , write message and can send plain mail or file attached mail using MFMailComposeViewController class. For more info : Sending e-mail from your iOS App

But, in this section what i am going to explain is about sending emails without showing the mail composer sheet ie. sending emails in background. For this feature, we can not use iOS native MFMailComposer class because it does not allow us to send emails in background instead it pop ups the mail composer view from where user have to tap "send" button , so for this section i am going to use  SKPSMTPMessage Library to send emails in background, however email account has to be hardcoded on this method.

Limitations :
1. sender/receiver email address has to be hardcoded or you have to grab it using some pop up form in your app where user inputs sender/receiver email address. In addition, sender account credentials has to be also hardcoded since there is no way we can grab it from device settings.

Method :
1. Import CFNetwork.framework to your project.
2. Include     #import "SKPSMTPMessage.h"
                    #import "NSData+Base64Additions.h" // for Base64 encoding
3. Include <SKPSMTPMessageDelegate> to your ViewController
4.  Download SKPSMTPMessage library from  
                                             https://github.com/jetseven/skpsmtpmessage
5. Drag and Drop "SMTPLibrary" folder you have downloaded to your project.

  Before proceeding, let you know that i am using sender/receiver email address and sender password hardcoded in the code for this example.But, you may grab this credentials from user, allowing them to input in some sort of forms(using UIViews).



-(void) sendEmailInBackground {
            NSLog(@"Start Sending");
            SKPSMTPMessage *emailMessage = [[SKPSMTPMessage alloc] init];
            emailMessage.fromEmail = @"sender@gmail.com"//sender email address
            emailMessage.toEmail = @"receiver@gmail.com";  //receiver email address
            emailMessage.relayHost = @"smtp.gmail.com";
            //emailMessage.ccEmail =@"your cc address";
           //emailMessage.bccEmail =@"your bcc address";
            emailMessage.requiresAuth = YES;
            emailMessage.login = @"sender@gmail.com"; //sender email address
            emailMessage.pass = @"Passwxxxx"; //sender email password
            emailMessage.subject =@"@"email subject header message";
            emailMessage.wantsSecure = YES
            emailMessage.delegate = self; // you must include <SKPSMTPMessageDelegate> to your class
           NSString *messageBody = @"your email body message";
         //for example :   NSString *messageBody = [NSString stringWithFormat:@"Tour Name: %@\nName: %@\nEmail: %@\nContact No: %@\nAddress: %@\nNote: %@",selectedTour,nameField.text,emailField.text,foneField.text,addField.text,txtView.text];
      // Now creating plain text email message
 NSDictionary *plainMsg = [NSDictionary
                        dictionaryWithObjectsAndKeys:@"text/plain",kSKPSMTPPartContentTypeKey,                               
 messageBody,kSKPSMTPPartMessageKey,@"8bit",kSKPSMTPPartContentTransferEncodingKey,nil];
  emailMessage.parts = [NSArray arrayWithObjects:plainMsg,nil];
            //in addition : Logic for attaching file with email message.
         /*
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"filename" ofType:@"JPG"];
    NSData *fileData = [NSData dataWithContentsOfFile:filePath];
    NSDictionary *fileMsg = [NSDictionary dictionaryWithObjectsAndKeys:@"text/directory;\r\n\tx-
unix-mode=0644;\r\n\tname=\"filename.JPG\"",kSKPSMTPPartContentTypeKey,@"attachment;\r\n\tfilename=\"filename.JPG\"",kSKPSMTPPartContentDispositionKey,[fileData encodeBase64ForData],kSKPSMTPPartMessageKey,@"base64",kSKPSMTPPartContentTransferEncodingKey,nil];
  emailMessage.parts = [NSArray arrayWithObjects:plainMsg,fileMsg,nil]; //including plain msg and attached file msg
            */
            [emailMessage send];
     // sending email- will take little time to send so its better to use indicator with message showing sending...
}

Now, handling delegate methods :
// On success

-(void)messageSent:(SKPSMTPMessage *)message{
    NSLog(@"delegate - message sent");
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Message sent." message:nil delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];
[alert show]; 
}
// On Failure
-(void)messageFailed:(SKPSMTPMessage *)message error:(NSError *)error{
// open an alert with just an OK button
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error!" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];
[alert show];
NSLog(@"delegate - error(%d): %@", [error code], [error localizedDescription]);
}

Ok, thats all from the coding side. hope this tutorial may find useful for you guyz.

In Addition, here are this list of issues  you may find during this tutorial and its solution :
1. If your project ARC is enabled and library has ARC disabled code  then you can disable your project ARC by going through your project target -> Build Settings ->Objective-c Automatic Reference Counting -> set NO
Or, if you only want to disable ARC for those library files only then  you can do it as :  To disable ARC for source files in Xcode 4, select the project and the target in Xcode. Under the target "Build Phases" tab, expand the Compile Sources build phase, select the library source files(.m file), then press Enter to open an edit field, and type -fno-objc-arc as the compiler flag for those files.
 
2. If you have encountered compiling error like  this in pic :




Then solution is go to your project target -> Build Phases -> Compile Sources -> add your all the .m class of your SMTP library . just like in this picture :

45 comments:

  1. Email said it was sent, but I never get the sent emails in my email account. Any ideas why?

    ReplyDelete
    Replies
    1. Your mail will not delivered if you send from simulator. It requires actual device.

      Delete
  2. Worked great, thank for the tutorial

    ReplyDelete
  3. its working fine but sometimes between in message state app crashing but mail sent can you provide me better solution for this situation.you can mail me pravesh19@gmail.com.

    ReplyDelete
  4. I am trying to send the image. Receiver is getting the mail, but the image he received is corrupted.
    Any idea? What can be the issue.

    ReplyDelete
  5. This was very helpful, thanks for the great tutorial.

    ReplyDelete
  6. tons of thanks man..you saved my day...lolzzzz

    ReplyDelete
  7. this code is show while running , unable to connect server alert view

    in log:
    2013-12-13 12:33:07.126 LocalNotificationDemo[92560:a0b] C: Attempting to connect to server at: smtp.gmail.com:25
    2013-12-13 12:33:07.140 LocalNotificationDemo[92560:a0b] delegate - error(-3): Unable to connect to the server.
    2013-12-13 12:33:07.140 LocalNotificationDemo[92560:a0b] dealloc
    2013-12-13 12:33:07.140 LocalNotificationDemo[92560:a0b] *** stopping watchdog ***

    ReplyDelete
  8. This type of error I'm getting any idea.?
    linker command failed with exit code 1 (use -v to see invocation)

    ReplyDelete
  9. This is not working in Iphone 5s ios 7

    ReplyDelete
  10. Skpsmtpmessage show DIFFERENT “From” adress , now i am from as i provide code username and password , can i change FROM as a custom

    ReplyDelete
  11. This comment has been removed by the author.

    ReplyDelete
  12. Nice insight Sameer. I'm often looking for new apps specially iOS latest launch for chatting and games app. You did a great job. Well done Sameer.

    ReplyDelete
  13. Nice code. Thanks a lot, your explanations were really useful

    ReplyDelete
  14. Geting error : "Please Login via webbrowser and try again".

    ReplyDelete
    Replies
    1. I am getting the same log.."Please Login via webbrowser and try again".. I am trying to solve this for so long time ..but i didn't get any solution..please help me to come out of this issue..please ....i need help

      Delete
    2. just go to "https://www.google.com/settings/security/lesssecureapps" and Turn on Access for less secure apps. Then it will works fine

      Delete
  15. Once i send the mail and if i check whether the i get the message or not even i give correct username and password,it does not work for me.

    ReplyDelete
  16. delegate - error(-3): Unable to connect to the server.

    ReplyDelete
  17. Thank you. Your blog was very helpful and efficient For Me,Thanks for Sharing the information. visit more info Gmail Support You can reach Acetecsupport at their Call Toll Free No +1-800-231-4635 For US/CA.

    ReplyDelete
  18. crash on this line [NSException raise:@"HSK_CFUtilitiesErrorDomain" format:@"Error writing bytes to stream!"] in HSK_CFUtilities.m file

    I don't understand why it crashes...Give me solution for this..

    ReplyDelete
  19. Cant sending Mail : Unsupported login mechanism. . Our android Team is able to send with this authenticate .
    I also used the same thing in iOS, But I am getting below error, Please give your valuable suggestion .

    Please, Find the below Log.

    2015-01-29 19:33:05.986 ARMHER[210:5598] Start Sending
    2015-01-29 19:33:06.640 ARMHER[210:5598] C: Attempting to connect to server at: mail.arm-her.com:25
    2015-01-29 19:33:07.338 ARMHER[210:5598] *** stopping watchdog ***
    2015-01-29 19:33:07.339 ARMHER[210:5598] S: 220 mail1401.opentransfer.com ESMTP
    2015-01-29 19:33:07.341 ARMHER[210:5598] C: EHLO localhost

    2015-01-29 19:33:07.342 ARMHER[210:5598] *** starting short watchdog ***
    2015-01-29 19:33:07.645 ARMHER[210:5598] *** stopping watchdog ***
    2015-01-29 19:33:07.646 ARMHER[210:5598] S: 250-mail1401.opentransfer.com
    2015-01-29 19:33:07.646 ARMHER[210:5598] *** stopping watchdog ***
    2015-01-29 19:33:07.647 ARMHER[210:5598] S: 250-PIPELINING
    2015-01-29 19:33:07.647 ARMHER[210:5598] *** stopping watchdog ***
    2015-01-29 19:33:07.647 ARMHER[210:5598] S: 250-8BITMIME
    2015-01-29 19:33:07.648 ARMHER[210:5598] *** stopping watchdog ***
    2015-01-29 19:33:07.648 ARMHER[210:5598] S: 250-SIZE 0
    2015-01-29 19:33:07.649 ARMHER[210:5598] *** stopping watchdog ***
    2015-01-29 19:33:07.649 ARMHER[210:5598] S: 250 AUTH LOGIN PLAIN CRAM-MD5
    2015-01-29 19:33:07.717 ARMHER[210:5598] delegate - error(-2): Unsupported login mechanism.
    2015-01-29 19:33:14.641 ARMHER[210:5598] dealloc
    2015-01-29 19:33:14.642 ARMHER[210:5598] *** stopping watchdog ***


    ReplyDelete
  20. Please, Inform to me in this Mail viswanath3344@gmail.com

    ReplyDelete
  21. How can i use this sksmtpmessage in swift? any code?

    ReplyDelete
  22. This comment has been removed by the author.

    ReplyDelete
  23. i am getting same error please help me.

    ReplyDelete
  24. Hello All,
    I wrote this blog on sending emails in background using SMTP library long time ago. So, I think SMTP library has been updated and we should go for the latest updates.
    I haven't been using it recently, so i can not help you with codes on this for now. But, I suggest you that please update your SMTP library and see the changes they have made on latest updates.

    Thank You for the feedbacks.

    ReplyDelete
  25. Great to read & learn from this blog, as it is highly informative about sending e-mail from iOS app. While exploring, I have also found an another iPhone developer forum which contains an another blog on Send mail using iOS at http://findnerd.com/list/view/Send-mail-using-iOS/4038/, Such type of knowledgeable content is beneficial for iOS developers.

    ReplyDelete
  26. Will Apple allow submission of apps where email is sent in the background, meaning without showing the MFMailComposeViewController UI to the user? I read on many stackoverflow threads that Apple may reject an app which use this mechanism. Any insights on that please.

    ReplyDelete
  27. What if My project is ARC Enabled

    ReplyDelete
  28. I implement this tutorial step by step i am not getting any error message and successful message
    always it shows the delegate - error(-5): Timeout sending message. what should i do? please help me out.

    I am using xcode 7.3 and OS 10.11.4 latest version.

    ReplyDelete
  29. 2016-04-19 11:50:55.600 BackGroundMail[1426:41648] S: 250 SMTPUTF8
    2016-04-19 11:50:55.601 BackGroundMail[1426:41648] C: AUTH PLAIN AGJoYXR0aXByYWRlZXA0MjZAZ21haWwuY29tADk0Mjk5MDc0MDQ=
    2016-04-19 11:50:55.601 BackGroundMail[1426:41648] *** starting short watchdog ***
    2016-04-19 11:50:56.213 BackGroundMail[1426:41648] *** stopping watchdog ***
    2016-04-19 11:50:56.213 BackGroundMail[1426:41648] S: 534-5.7.14 Please log in via your web browser and
    2016-04-19 11:50:56.215 BackGroundMail[1426:41648] *** stopping watchdog ***
    2016-04-19 11:50:56.215 BackGroundMail[1426:41648] S: 534-5.7.14 then try again.
    2016-04-19 11:50:56.215 BackGroundMail[1426:41648] *** stopping watchdog ***
    2016-04-19 11:50:56.215 BackGroundMail[1426:41648] S: 534-5.7.14 Learn more at
    2016-04-19 11:50:56.215 BackGroundMail[1426:41648] *** stopping watchdog ***
    2016-04-19 11:50:56.215 BackGroundMail[1426:41648] S: 534 5.7.14 https://support.google.com/mail/answer/78754 ee5sm809987pac.35 - gsmtp

    pls help me i'm not proprelly understand what to do. so pls help me

    ReplyDelete
  30. it works. thank you very much

    ReplyDelete
  31. 2016-05-26 18:13:41.324 xxx[1771:70b] C: Attempting to connect to server at: smtp.gmail.com:25
    2016-05-26 18:13:49.333 xxx[1771:70b] C: Attempting to connect to server at: smtp.gmail.com:465
    2016-05-26 18:13:57.350 xxx[1771:70b] C: Attempting to connect to server at: smtp.gmail.com:587
    2016-05-26 18:13:57.620 xxx[1771:70b] *** stopping watchdog ***
    2016-05-26 18:13:57.620 xxx[1771:70b] S: 220 smtp.gmail.com ESMTP v185sm5504420pfb.72 - gsmtp
    2016-05-26 18:13:57.620 xxx[1771:70b] C: EHLO localhost
    2016-05-26 18:13:57.621 xxx[1771:70b] *** starting short watchdog ***
    2016-05-26 18:13:57.834 xxx[1771:70b] *** stopping watchdog ***
    2016-05-26 18:13:57.835 xxx[1771:70b] S: 250-smtp.gmail.com at your service, [183.83.226.132]
    2016-05-26 18:13:57.835 xxx[1771:70b] *** stopping watchdog ***
    2016-05-26 18:13:57.835 xxx[1771:70b] S: 250-SIZE 35882577
    2016-05-26 18:13:57.835 xxx[1771:70b] *** stopping watchdog ***
    2016-05-26 18:13:57.836 xxx[1771:70b] S: 250-8BITMIME
    2016-05-26 18:13:57.836 xxx[1771:70b] *** stopping watchdog ***
    2016-05-26 18:13:57.836 xxx[1771:70b] S: 250-STARTTLS
    2016-05-26 18:13:57.837 xxx[1771:70b] C: STARTTLS
    2016-05-26 18:13:57.837 xxx[1771:70b] *** starting short watchdog ***
    2016-05-26 18:13:57.838 xxx[1771:70b] *** stopping watchdog ***
    2016-05-26 18:13:57.838 xxx[1771:70b] S: 250-ENHANCEDSTATUSCODES
    2016-05-26 18:13:57.839 xxx[1771:70b] *** stopping watchdog ***
    2016-05-26 18:13:57.839 xxx[1771:70b] S: 250-PIPELINING
    2016-05-26 18:13:57.839 xxx[1771:70b] *** stopping watchdog ***
    2016-05-26 18:13:57.839 xxx[1771:70b] S: 250 SMTPUTF8
    2016-05-26 18:13:58.051 xxx[1771:70b] *** stopping watchdog ***
    2016-05-26 18:13:58.051 xxx[1771:70b] S: 220 2.0.0 Ready to start TLS
    2016-05-26 18:13:58.052 xxx[1771:70b] Beginning TLSv1...
    2016-05-26 18:13:58.053 xxx[1771:70b] C: EHLO localhost
    2016-05-26 18:13:58.249 xxx[1771:70b] CFNetwork SSLHandshake failed (-9807)
    2016-05-26 18:13:58.253 xxx[1771:70b] delegate - error(-9807): The operation couldn’t be completed. (OSStatus error -9807.)
    2016-05-26 18:14:05.351 xxx[1771:70b] dealloc
    2016-05-26 18:14:05.351 xxx[1771:70b] *** stopping watchdog ***


    i am getting thz msg... plz help me out what to do ..

    ReplyDelete
  32. This comment has been removed by the author.

    ReplyDelete
  33. This is tooo old, current xcode doesnt allow this . It has ARC used and lot of errors. Please upgrade this code.

    ReplyDelete
  34. If you are having problem to send email with gmail over 3G network from your mobile device, just login to your email on browser, then hit following links

    https://accounts.google.com/b/0/DisplayUnlockCaptcha

    ReplyDelete