要我说呀,你如果不曾碰到奇奇怪怪的需求都不好意思说你是个程序猿。最近我碰到了,所以才有这篇文章,记录一下过程中遇到的问题。

这篇文章是记录一下我是如何在iOS端实现自动发送邮件功能的。某个应用场景为:

用户点击iOS端的”发送邮件”按钮,其功能是将某些数据以邮件的形式自动发送到用户的邮箱。

iOS端向特定SMTP服务器发起请求,发送邮件。

经过一段时间的百度(好孩子不翻qiang),我了解到,iOS发送邮件目前有3种实现方式:

使用openURL来实现发邮件的功能

使用MFMailComposeViewController来实现发邮件的功能

使用比较有名的开源SMTP协议来实现,例如SKPSMTPMessage

前两者会跳出当前页面,与我们”自动发送”的要求不符,所以我们使用开源的SKPSMTPMessage实现功能。

如果你只是想知道怎么解决乱码问题,请转到最后。

skpsmtpmessage介绍

skpsmtpmessage 简单的封装了SMTP协议,让你的app可以发送邮件。它是手动封装的,有很大的自由度,可以在后台发送请求,从而自动发送邮件。skpsmtpmessage源码见github

需要注意的一点是,你最好

To use this in your app, add the files in the SMTPLibrary directory to your project.

原因是,Cocoapod里的skpsmtpmessage版本较老,会引起标题中文乱码的问题。

不得不吐槽一句,iOS的SMTP封装的第三方开源库真的好少,我找来找去就找到这一个陈年老库,而Java的类似库印象中比比皆是。

不得不再吐槽一句,让移动端自动发送邮件的需求也是挺少见的。我没文化所以觉得发送邮件应该是放在后台来实现的。

基本使用

发送邮件

直接放代码吧,使用上很方便直观。

SKPSMTPMessage *testMsg = [[SKPSMTPMessage alloc] init];

testMsg.fromEmail = @"your email";

testMsg.toEmail = @"target email";

testMsg.relayHost = @"smtp server";

testMsg.requiresAuth = YES;//是否需要认证(登陆)

testMsg.login = @"登陆账号";

testMsg.pass = @"password";

testMsg.delegate = sender;//指定delegate

//testMsg.bccEmail = [defaults objectForKey:@"bccEmal"];//这个不知道干嘛的。。。找不到资料

testMsg.wantsSecure = NO;//是否用ssl

testMsg.subject = @"SMTPMessage Test Message,测测试试";

NSDictionary *plainPart = [NSDictionary dictionaryWithObjectsAndKeys:@"text/plain; charset=UTF-8",kSKPSMTPPartContentTypeKey,

@"邮件由系统自动发送,请勿回复。",kSKPSMTPPartMessageKey,@"8bit",kSKPSMTPPartContentTransferEncodingKey,nil];

testMsg.parts = [NSArray arrayWithObjects:plainPart,nil];

dispatch_async(dispatch_get_main_queue(), ^{

[testMsg send];

});

你也可以添加附件,除了以上代码,你需要做的是

首先,添加附件块

NSString *vcfPath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"vcf"];

NSData *vcfData = [NSData dataWithContentsOfFile:vcfPath];

NSDictionary *vcfPart = [NSDictionary dictionaryWithObjectsAndKeys:@"text/directory;\r\n\tx-unix-mode=0644;\r\n\tname=\"test.vcf\"",kSKPSMTPPartContentTypeKey,@"attachment;\r\n\tfilename=\"test.vcf\"",kSKPSMTPPartContentDispositionKey,[vcfData encodeBase64ForData],kSKPSMTPPartMessageKey,@"base64",kSKPSMTPPartContentTransferEncodingKey,nil];

然后,在test.parts中加上刚才的附件块

testMsg.parts = [NSArray arrayWithObjects:plainPart,vcfPart,nil];

以上代码大部分来自skpsmtpmessage提供的Demo,需要注意的是,demo中使用多线程发送邮件,而我刚才的代码是在主线程发送邮件,原因是,在多线程环境,邮件无法发送成功。这与其内部机制有关,我暂时没看出个所以然。看以后会不会有兴趣研究研究。

发送之后

发送之后,会调用delegate方法。

成功,调用:

- (void)messageSent:(SKPSMTPMessage *)message;

失败,调用:

- (void)messageFailed:(SKPSMTPMessage *)message error:(NSError *)error;

标题中文乱码解决方法

这个问题解决方法就一个,使用github上的skpsmtpmessage库,不要用cocoapods,因为cocoapods上的代码是老代码,没有修复标题乱码的问题。

具体的改动是:

SKPSMTPMessage.m的sendParts里

NSData *messageData = [message dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

改为

NSData *messageData = [message dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];

之前用ASCII的编码,所以会乱码。现在改为utf8就好了。

附件文件名中文乱码解决方法

当我在邮箱的页面点击下载附件时,附件的文件名是乱码的形式。百度了好久,没有找到skpsmtpmessage库解决这个问题的办法。唯一一个遇到同样问题的哥们在他的博客上说,虽然附件的文件名中文乱码,但是我们用英文就好了。

于是我从Java的类似类库着手,查阅附件名中文乱码的资料,很容易找到了解决方案。

用上面的附件代码,修改一下即可。修改前:

NSString *vcfPath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"vcf"];

NSData *vcfData = [NSData dataWithContentsOfFile:vcfPath];

NSDictionary *vcfPart = [NSDictionary dictionaryWithObjectsAndKeys:@"text/directory;\r\n\tx-unix-mode=0644;\r\n\tname=\"测试.vcf\"",kSKPSMTPPartContentTypeKey,@"attachment;\r\n\tfilename=\"测试.vcf\"",kSKPSMTPPartContentDispositionKey,[vcfData encodeBase64ForData],kSKPSMTPPartMessageKey,@"base64",kSKPSMTPPartContentTransferEncodingKey,nil];

以上代码,文件名为 测试.vcf,当作为附件发送到目标邮箱后,用户下载邮件,附件文件名为乱码.

但是可以修改成一下形式

NSString *vcfPath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"vcf"];

NSString *encodeFileName = [NSString stringWithFormat:@"=?UTF-8?B?%@?=",[[@"测试.vcf" dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0]];

NSData *vcfData = [NSData dataWithContentsOfFile:vcfPath];

NSDictionary *vcfPart = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"text/directory;\r\n\tx-unix-mode=0644;\r\n\tname=\"%@\"",encodeFileName],kSKPSMTPPartContentTypeKey,[NSString stringWithFormat:@"attachment;\r\n\tfilename=\"%@\"",encodeFileName],kSKPSMTPPartContentDispositionKey,[vcfData encodeBase64ForData],kSKPSMTPPartMessageKey,@"base64",kSKPSMTPPartContentTransferEncodingKey,nil];

其中的重点是修改了filename,对其进行处理。

例如:

=?UTF-8?B?5LiA5Y+35bqXNOWRqOW5tOW6hu+8jDEwMDDkuIfku7bng63plIA=?=

这个是邮件头的编码格式,B表示是Base64编码,UTF-8表示字符集的编码。

5LiA5Y+35bqXNOWRqOW5tOW6hu+8jDEwMDDkuIfku7bng63plIA=

就是标题base64之后的结果。

使用这个就可以使附件的中文名不再乱码。

java ios乱码_iOS发送邮件及其中文乱码解决方法相关推荐

  1. java web乱码问题_Java Web中文乱码问题解决

    一.为什么会出现中文乱码问题: java内核和class文件是基于unicode码的,这使Java程序具有良好的跨平台性,但也导致在Java和JSP文件在编译时以及Java程序与其他媒介交互时等情况下 ...

  2. ios html中文显示乱码,iOS读取txt文件出现中文乱码的解决方法

    一.情景描述: 后台给一个txt文件,编码是utf-8,在mac电脑xcode开发环境下读取txt文件内容,汉字会出现乱码,英文没有乱码这种情况. 二.尝试解决方法: 修改编码格式,尝试了nsutf1 ...

  3. linux mysql插入数据乱码_linux mysql数据库中文乱码

    mysql中文乱码 mysql是我们项目中非常常用的数据型数据库.但是因为我们需要在数据库保存中文字符,所以经常遇到数据库乱码情况.下面就来介绍一下如何彻底解决数据库中文乱码情况. 1.中文乱码 1. ...

  4. vscode新建html中文乱码,vscode中html中文乱码 怎么办

    vscode中html中文乱码 怎么办?VSCode 中文乱码解决办法 文件 >> 首选项 >> 设置 搜索:"files.autoGuessEncoding&quo ...

  5. mysql数据库 中文乱码_数据库 MySQL中文乱码解决办法总结

    MySQL中文乱码解决办法 前言: MySQL是我们项目中非常常用的数据型数据库.但是因为我们需要在数据库保存中文字符,所以经常遇到数据库乱码情况.下面就来介绍一下如何彻底解决数据库中文乱码情况. 1 ...

  6. exp/imp 注释乱码问题或Oracle EXP-00091的解决方法

    exp/imp 注释乱码问题或Oracle EXP-00091的解决方法 参考文章: (1)exp/imp 注释乱码问题或Oracle EXP-00091的解决方法 (2)https://www.cn ...

  7. 【Ubuntu】安装中文输入法、终端不支持中文的解决方法

    一.中文输入法安装 1.安装汉语语言包 sudo apt install fcitx sudo apt install language-pack-zh-hans 2.安装google拼音输入法 su ...

  8. opengl中的Floatbuffer和IntBuffer与java中数据的存储方式不同的解决方法,编辑一个自己的BufferUtil工具类

    opengl中的Floatbuffer和IntBuffer与java中数据的存储方式不同的解决方法,编辑一个自己的BufferUtil工具类 参考文章: (1)opengl中的Floatbuffer和 ...

  9. 我爱Java系列---【 maven依赖版本冲突的解决方法】

    我爱Java系列---[ maven依赖版本冲突的解决方法] 参考文章: (1)我爱Java系列---[ maven依赖版本冲突的解决方法] (2)https://www.cnblogs.com/hu ...

最新文章

  1. 在Ubuntu 16.04.3 LTS上安装Go 1.10
  2. python 培训-本人的Python自学历程分享
  3. 全球云计算大会起航,网易云阮良解读人工智能在产品中的创新实践
  4. 云服务器怎么查看文件目录结构,查看云服务器目录结构图
  5. ios开发网络学习:一:NSURLConnection发送GET,POST请求
  6. Flink1.12.0使用过程中遇到的异常
  7. “超大杯”版小米10被曝8月中下旬发布:100W快充实锤 处理器却成迷
  8. 俄罗斯黑客入侵冬奥会系统,还甩锅给朝鲜?
  9. HTML5移动Web开发(六)——定义一个内容策略
  10. linux内核启动后键盘不能用,编译linux-0.11内核后键盘不对的问题解决方法,比如/变成了-...
  11. oracle 启动报错03113,oracle数据库无法启动,总报ora-03113错误
  12. visio用例图箭头怎么画_Visio画图(一):UML用例图
  13. Thinkphp聊天室H5实时聊天室群聊聊天室自动分配账户完群组私聊禁言等功能全开源运营版本
  14. 跨越适配性能那道坎,企鹅电竞Android weex优化
  15. 附合导线坐标计算例题_附合导线坐标计算
  16. Hadoop 安装指南
  17. BZOJ4484: [Jsoi2015]最小表示
  18. Python批量自动下载获取图片
  19. 使用opencv和C++实现多焦距图像合成
  20. C语言中求最大公约数的算法(三种)

热门文章

  1. transactionManager手动事物管理--记一次重大的生产事故
  2. 用python进行主成分分析(PCA)
  3. 《你的知识需要管理》读书笔记
  4. 人人网(带有登陆页面的网站爬取)
  5. std::copy性能分析与memmove机器级实现
  6. OK6410开发板linux系统下的SPI驱动和测试
  7. 模拟器键盘Can't find keyplane that supports type 4 for keyboard iPhone-PortraitChoco-NumberPad
  8. Creo/Proe 二次开发中使用 QT 编程流程
  9. 以下选项中、不是python对文件的打开模式的是_关于Python文件打开模式的描述,以下选项中错误的是()。...
  10. P34 字符串类型的函数讲解