由于最近公司业务需求,须要用到静默方式发送邮件的功能,因此接触到了SKPSMTPMessage这个第三方库。话说iOS有关SMTP封装的第三方库真的好少惹,仅有的这么一个库还年久失修,网上的资料也较少并且不少有误的,致使使用过程当中真的遇到了很是多的坑,因此在这里跟你们分享一下我使用过程当中遇到的问题跟解决方案,但愿对你们有所帮助,若有不对的地方欢迎指正哈。比心❤️😁html
基本使用:ios
SKPSMTPMessage *Msg = [[SKPSMTPMessage alloc] init];
Msg.fromEmail = @"发件人邮箱";
Msg.toEmail = @"收件人邮箱";
Msg.relayHost = @"smtp.126.com";//发送邮件代理服务器(这里我用的是126邮箱作的示范)
Msg.requiresAuth = YES;//是否须要认证(登录)
Msg.login = @"发件人邮箱帐号";
Msg.pass = @"密码或者受权码";//
Msg.delegate = self;
Msg.wantsSecure = YES;//是否用ssl
//Msg.validateSSLChain = NO;//是否验证SSL证书
Msg.subject = @"邮件标题";//邮件标题
//1.邮件内容: 正文文字
NSDictionary *plainPart = [NSDictionary dictionaryWithObjectsAndKeys:@"text/plain; charset=UTF-8",kSKPSMTPPartContentTypeKey,
@"邮件由系统自动发送,请勿回复。",kSKPSMTPPartMessageKey,@"8bit",kSKPSMTPPartContentTransferEncodingKey,nil];
dispatch_async(dispatch_get_main_queue(), ^{
//发送邮件
[Msg send];
});
发送以后,会调用delegate方法。
//成功,调用:
- (void)messageSent:(SKPSMTPMessage *)message;
//失败,调用:
- (void)messageFailed:(SKPSMTPMessage *)message error:(NSError *)error;
复制代码
网上不少教程都是直接开启多线程发送,但经我测试行不通,没法链接服务器。git
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[Msg send];
});
复制代码
提示错误:SMTP服务器链接失败github
C: Attempting to connect to server at:smtp.126.com:2025**bash
解决方法: 1.须要在后面再加一个运行循环: [[NSRunLoop currentRunLoop] run]; 由于若是建立新线程,runloop不会自动运行; 咱们必须手动启动,要否则重试其余端口的操做不会进行。服务器
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[Msg send];
[[NSRunLoop currentRunLoop] run];
});
复制代码
2.或者在主线程中发送邮件多线程
dispatch_async(dispatch_get_main_queue(), ^{
[myMsg send];
});
复制代码
1.发送者邮箱须要开启SMTP服务,否则邮件没法从发送方邮箱发出。async
Msg.relayHost = @"smtp.126.com";
//发送邮件代理服务器(这里我用的是126邮箱作的示范,若是你用的是公司邮箱那就填的公司的SMTP服务器地址)
复制代码
2.目前广泛的一些第三方邮箱(如QQ、163邮箱等)如今都须要设置受权码才能正常发送邮件。oop
Msg.pass = @"受权码";
复制代码
这是126邮箱开启受权码的示范,在邮箱设置便可:测试
Msg.pass = @"邮箱密码";
复制代码
1.标题中文乱码
致使乱码的缘由是由于SKPSMTPMessage库以前使用的是ASCII的编码,因此咱们把它改成utf8便可。
//咱们只须要将SKPSMTPMessage.m里如下这句代码:
NSData *messageData = [message dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
//改成这句代码就行了
NSData *messageData = [message dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
复制代码
2.附件中文标题乱码
这里我用发送图片附件作的示范
代码修改前:
UIImage *image = [UIImage imageNamed:@"WechatIMG372"];
//图片大于1M时建议作压缩处理
NSData *imgData = UIImageJPEGRepresentation(image,1.0f);
NSDictionary *imgPart = [NSDictionary dictionaryWithObjectsAndKeys:@"image/jpg;\r\n\tx-unix-mode=0644;\r\n\tname=\"图片附件名.jpg\"",kSKPSMTPPartContentTypeKey,
@"attachment;\r\n\tfilename=\"图片附件名.jpg\"",kSKPSMTPPartContentDispositionKey,[imgData encodeBase64ForData],kSKPSMTPPartMessageKey,@"base64",kSKPSMTPPartContentTransferEncodingKey,nil];
复制代码
代码修改后:
UIImage *image = [UIImage imageNamed:@"WechatIMG372"];
//图片大于1M时建议作压缩处理
NSData *imgData = UIImageJPEGRepresentation(image,1.0f);
NSString *encodeFileName = [NSString stringWithFormat:@"=?UTF-8?B?%@?=",[[@"附件标题名" dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0]];
//解决附件中文乱码的问题
NSDictionary *imagePart = [NSDictionary dictionaryWithObjectsAndKeys: [NSString stringWithFormat:@"image/jpg;\r\n\tx-unix-mode=0644;\r\n\tname=\"%@.jpg\"",encodeFileName],kSKPSMTPPartContentTypeKey,
[NSString stringWithFormat:@"attachment;\r\n\tfilename=\"%@\"",encodeFileName],kSKPSMTPPartContentDispositionKey,[imgData encodeBase64ForData],kSKPSMTPPartMessageKey,@"base64",kSKPSMTPPartContentTransferEncodingKey,nil];
复制代码
能够看到以上代码重点是修改了filename,对其进行处理。 例如:这个是邮件头的编码格式,B表示是Base64编码,UTF-8表示字符集的编码。
=?UTF-8?B?6ZmE5Lu25qCH6aKY5ZCN?=
使用这个就可使附件的中文名再也不乱码。
在我将上面的坑都填完以后,使用第三方邮箱来收发邮箱都是没有问题的,可是在我使用公司邮箱做为发件者邮箱的时候却报了这个错误:
error - Error Domain=NSOSStatusErrorDomain Code=-9807 "(null)" UserInfo={_kCFStreamErrorCodeKey=-9807, _kCFStreamErrorDomainKey=3}
网上没有找到这个问题的解决方法,只有有关于9807这个错误的解释:
由于咱们公司邮箱是用的本身的服务器,公司的服务器是没有作相关证书验证的,因此基本能肯定是是证书的缘由了。SKPSMTPMessage库里有为咱们提供一个BOOL值的属性:validateSSLChain,这个属性是用来验证证书链的,默认是YES;我将他改成NO邮件就顺利发送成功了。
myMsg.validateSSLChain = NO;//关闭证书链的验证
复制代码
废话很少说先上代码:
//4.正文插入图片
//4.1图片转base64字符串
NSString *baseStr = [imgData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
//4.2 正文文本html
NSString *str = @"<p style=\"color:black\">正文测试测试测试</p>";
///</p><img src=\"data:image/png;base64," ;
//4.3 图片html
NSString *str1 = @"<img src=\"data:image/png;base64,";
NSString *str2 = @"\" />";
//将图片base64字符串与html标签拼接
NSString *imgHtml = [NSString stringWithFormat:@"%@%@%@",str1,baseStr,str2];
//4.4 拼接出正文加图片的html字符串
NSString *body = [NSString stringWithFormat:@"%@%@",str,imgHtml];
NSDictionary *htmlPart = [NSDictionary dictionaryWithObjectsAndKeys:@"text/html;charset=UTF-8",kSKPSMTPPartContentTypeKey,
body,kSKPSMTPPartMessageKey,@"8bit",kSKPSMTPPartContentTransferEncodingKey,nil];
Msg.parts = [NSArray arrayWithObjects:htmlPart,nil];
复制代码
这个问题我网上找了好久都没有找到解决方案,由于SKPSMTPMessage库part的元素字典一个key只能单独设置一种格式,像 text/plain或者image/jpg等;同时设置2个格式的话会报错,试了不少方法都不行,最后换了个思路使用text/html格式解决了这个问题。
1.咱们要把text/plain这个key替换成text / html
//body: html文本
NSDictionary *htmlPart = [NSDictionary dictionaryWithObjectsAndKeys:@"text/html;charset=UTF-8",kSKPSMTPPartContentTypeKey,
body,kSKPSMTPPartMessageKey,@"8bit",kSKPSMTPPartContentTransferEncodingKey,nil];
复制代码
2.使用html标签拼接出正文跟图片
起初我是用富文本生成html字符串的,可是这种方式生成的html字符串发送过去显示一堆乱码,后来就直接改用html标签来实现了,实现过程有点low,你们若是有更好的实现方法也能够在评论下方告诉我。
//1.文本html标签
"<p style=\"color:black\">正文文本文字</p>";
//2.图片html标签
<img src="data:image/png;base64,图片base64字符串" />
//3.把文本html跟图片html按照你的需求拼接便可
复制代码
3.上面代码最终实现效果:(我使用的QQ邮箱作的收件邮箱)