Java实现QQ邮件发送客户端
目录
一、前言:QQ邮件发送程序
在上一篇《Java网络编程:实现QQ邮件发送客户端》,我们解决了telnet终端发送邮件误操作带来的麻烦,实现了自己的简单Java界面进行发送QQ邮件,界面可直接与smtp.qq.com服务器端建立连接,通过命令方式发送邮件信息。
这一篇为QQ邮件发送客户端程序设计的下篇,将实现更加完善的功能,不用命令发送方式,类似日常发送邮件,直接编写邮件标题、内容,然后直接发送即可,基本实现了QQ邮件发送客户端的功能,操作更加简便,实现自己的QQ邮件发送端,以后就用这个啦。
二、封装SMTP操作
原来的终端发送逐步操作如下:
- HELO hostname //回车,hostname可以是IP或其他随意别名
- AUTH LOGIN //回车后,先粘贴base64程序编码的完整邮箱名并回车;再粘贴base64编码的授权码并回车
- MAIL FROM:<czh_charzeus@qq.com> //在这里填写自己的邮箱地址,用于发送邮件(注意冒号后面别有空格)
- RCPT TO:<czh_charzeus@qq.com> //接收方的邮箱,在这里暂时填写和上面一样的邮箱地址,即自己发送邮件给自己,验证是否成功
- DATA //回车,接下来开始发送邮件头相关内容
- Subject: the simple mail // 邮件的标题,回车
- //在这里再多发送一行空行,来分隔邮件内容,下面就是邮件正文内容
- Hello,the mail content!
- 测试发送邮件! //控制台中中文会变成?的乱码,但不影响接受者接收到中文内容
- . //在邮件正文发送完毕后,单独用一行输入一个小圆点,作为结束标志,然后回车
- QUIT //结束通信(含4次握手断开)
因此,我们要避免这种繁琐的命令形式,只需要将每个语句封装到发送程序里面,在用户界面则无需进行命令的输入,只需要输入内容。
实现的方法很简单,只需要在发送按钮中,把命令加进去就可以,如下:
- tcpMailClient.send("HELO friend");
- tcpMailClient.send("auth login");
- String userNameBase64= encode(senderMail);
- tcpMailClient.send(userNameBase64);
- String authCode = encode("你的授权码");
- tcpMailClient.send(authCode);
- String msg = "mail from:<"+senderMail+">";
- tcpMailClient.send(msg);
- msg = "rcpt to:<"+receiverMail+">";
- tcpMailClient.send(msg);
- tcpMailClient.send("data");
- msg="from:"+senderMail;
- tcpMailClient.send(msg);
- msg="to:"+receiverMail;
- tcpMailClient.send(msg);
- msg="subject:"+sub;
- tcpMailClient.send(msg);
- tcpMailClient.send("\n");
- // tcpMailClient.send("这是一封测试java客户端自动发送功能的邮件。");
- tcpMailClient.send(content);
- tcpMailClient.send(".");
- tcpMailClient.send("quit");
从代码可以看到,当发送按钮一点击后,程序会执行所有语句,我们从上一篇知道,邮件服务器也会返回信息,所以QQ客户端需要使用多线程的技术,来处理返回信息,避免单线程阻塞导致发送不成功。
三、实现多线程接收
根据前面分析,将客户端接收的功能交给一个线程处理,就能够达到目的,不会因为接收语句阻塞使得主进程卡住。
所以,将线程放到连接按钮里面为好,在成功连接服务器之后,程序就启动线程,时机正好。连接按钮中的线程代码如下:
- //用于接收服务器信息的单独线程
- readThread = new Thread(()->{
- String receiveMsg=null;//从服务器接收一串字符
- while ((receiveMsg=tcpMailClient.receive())!=null){
- String msgTemp = receiveMsg;
- Platform.runLater(()->{
- taDisplay.appendText(msgTemp+"\n");
- });
- }
- Platform.runLater(()->{
- taDisplay.appendText("对话已关闭!\n");
- });
- });
- readThread.start();
程序执行发送每一条命令语句的速度比我们自己输入发送要快许多,为了避免QQ邮件接收服务器无法及时响应出错,程序自动发送过程中需要设置一定的睡眠等待时间,在send方法设置等待200ms或者500ms。
QQ邮件客户端实现代码可见上一篇Java网络编程:实现QQ邮件发送客户端,这里不再重复介绍。
- public void send(String msg){
- //输出字符流,由socket调用系统底层函数,经网卡发送字节流
- pw.println(msg);
- try {
- //进行邮件交互,发送smtp指令之间应该暂停一段时间
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
四、QQ邮件客户端界面设计
界面的设计与以往类似,可以根据自己的需求设计不同的界面风格,可参考本文前言或者总结部分的系列文章进行实现。这里给出关键按钮的完整代码。
1、连接按钮


- //连接按钮
- btConn.setOnAction(event -> {
- String ip=ipAddress.getText().trim();
- String port=tfport.getText().trim();
- try {
- tcpMailClient = new TCPMailClient(ip, port);
- //成功连接服务器,接受服务器发来的第一条欢迎信息
- String firstMsg=tcpMailClient.receive();
- taDisplay.appendText(firstMsg+"\n");
- //用于接收服务器信息的单独线程
- readThread = new Thread(()->{
- String receiveMsg=null;//从服务器接收一串字符
- while ((receiveMsg=tcpMailClient.receive())!=null){
- //lambda表达式不能直接访问外部非final类型局部变量,需要定义一个临时变量
- //若将receiveMsg定义为类成员变量,则无需临时变量
- String msgTemp = receiveMsg;
- Platform.runLater(()->{
- taDisplay.appendText(msgTemp+"\n");
- });
- }
- Platform.runLater(()->{
- taDisplay.appendText("对话已关闭!\n");
- });
- });
- readThread.start();
- } catch (IOException e) {
- e.printStackTrace();
- }
- });
2、发送按钮


- //发送按钮
- btnSend.setOnAction(event -> {
- String senderMail = mail.getText().trim();
- String receiverMail = toMail.getText().trim();
- String sub = subject.getText();
- String content = tfSend.getText();
- try {
- tcpMailClient.send("HELO friend");
- tcpMailClient.send("auth login");
- String userNameBase64= encode(senderMail);
- tcpMailClient.send(userNameBase64);
- String authCode = encode("你的授权码");
- tcpMailClient.send(authCode);
- String msg = "mail from:<"+senderMail+">";
- tcpMailClient.send(msg);
- msg = "rcpt to:<"+receiverMail+">";
- tcpMailClient.send(msg);
- tcpMailClient.send("data");
- msg="from:"+senderMail;
- tcpMailClient.send(msg);
- msg="to:"+receiverMail;
- tcpMailClient.send(msg);
- msg="subject:"+sub;
- tcpMailClient.send(msg);
- tcpMailClient.send("\n");
- // tcpMailClient.send("这是一封测试java客户端自动发送功能的邮件。");
- tcpMailClient.send(content);
- tcpMailClient.send(".");
- tcpMailClient.send("quit");
- }catch (Exception e){
- taDisplay.appendText("服务器连接失败!"+e.getMessage()+"\n");
- }
- });
QQ客户端的程序可以沿用之前的内容,详见这篇:基于TCP协议网络socket编程(java实现C/S通信)
五、QQ邮件发送效果演示
细心的读者可以发现,在我点击发送之后,程序卡断了一会,其实就是因为我设置发送睡眠1000ms,实际可以发送成功,建议设置200ms或以上!
发送到自己QQ邮箱:
发送到自己的126邮箱进行测试:
六、总结
这一篇为QQ邮件发送客户端程序设计的下篇,记录了实现的关键部分,不用命令发送方式,类似日常发送邮件,直接编写邮件标题、内容,然后直接发送即可,基本实现了QQ邮件发送客户端的功能,操作更加简便。根据本篇的知识内容,后面可以实现更加完善的QQ邮件发送小程序,增加一系列小功能!
如果觉得不错欢迎“一键三连”哦,点赞收藏关注,有问题直接评论,交流学习!
我的博客园:https://www.cnblogs.com/chenzhenhong/p/14331829.html
我的CSDN博客:https://blog.csdn.net/Charzous/article/details/111148425
Java实现QQ邮件发送客户端的更多相关文章
- Java网络编程:QQ邮件发送客户端程序设计
目录 一.目标介绍 1.认识SMTP(邮件传输协议) 2.POP3(邮件接收协议) 二.基于Base64编码邮箱及授权码 1.开通QQ邮箱SMTP/POP3服务 2.Java编写BASE64编码程序 ...
- Java实现QQ邮件发送
首先我们需要两个jar包,点击下面即可下载这两个包: JavaMail mail.jar 1.4.5 JAF(版本 1.1.1) activation.jar 我们这里采用QQ邮箱发送邮件为例,代码如 ...
- JAVA 实现 QQ 邮箱发送验证码功能(不局限于框架)
JAVA 实现 QQ 邮箱发送验证码功能(不局限于框架) 本来想实现 QQ 登录,有域名一直没用过,还得备案,好麻烦,只能过几天再更新啦. 先把实现的发送邮箱验证码更能更新了. 老规矩,更多内容在注释 ...
- Spring进阶—如何用Java代码实现邮件发送(一)
相关文章: <Spring进阶—如何用Java代码实现邮件发送(二)> 在一些项目里面如进销存系统,对一些库存不足发出预警提示消息,招聘网站注册用户验证email地址等都需要用到邮件发送技 ...
- 线程——QQ邮件发送
一.造一个QQ邮件发送的窗体 二.开始编写关于邮件发送的代码,以及当点发送按钮的时候,给发送按钮单独造了一个新的线程.这样如果发送的附件太多的话,如果不给发送按钮造新的线程,便会卡住,但是如果给发送按 ...
- java实现smtp邮件发送
一.准备工作 首先你需要已一个发送邮箱,一般的邮箱都有SMTP.POP3服务,比如QQ邮箱,登陆QQ邮箱开启SMTP服务,开启是服务器会提示你设置独立密码,这个密码是跟邮箱正常登陆的密码不同的,这个是 ...
- Java实现多线程邮件发送
利用java多线程技术配合线程池实现多任务邮件发送. 1.基本邮件发送MailSender package hk.buttonwood.ops.email; import java.io.File; ...
- java简单的邮件发送
java实现简单的邮件发送案例,学会了这个你就可以利用这个来整你的好友了,不断地给他进行邮箱轰炸(当然个人不建议瞎搞),最重要的是明白其中的原理最好了.话不多说,直接看代码案例了.首先需要导入的jar ...
- python定时利用QQ邮件发送天气预报
大致介绍 好久没有写博客了,正好今天有时间把前几天写的利用python定时发送QQ邮件记录一下 1.首先利用request库去请求数据,天气预报使用的是和风天气的API(www.heweather.c ...
随机推荐
- 【Objective-C】1.oc点语法
在Java中,我们可以通过"对象名.成员变量名"来访问对象的公共成员变量,这个就称为"点语法".比如: 1.在Student类的第2行定义了一个公共的成员变量a ...
- SpringBoot 与 SpringSecurity
一.环境搭建 (1)IDEA创建SpringBoot工程 (2)导入依赖 (3)如果是thymeleaf项目 需导入thymeleaf整合security的依赖 (4)编写配置类(采用AOP横切入程序 ...
- 如何对项目中的问题进行分析——FPGA失败案例小结
本人最近在做一个小项目,自己取名叫做<基于zedboard的千兆以太网底层设计>,一般我都是写好各模块的verilog代码,确定模块没bug后再做整个系统级联,之后直接先进行综合看看有没有 ...
- 高端面试必备:一个Java对象占用多大内存
这个问题一般会出现在稍微高端一点的 Java 面试环节.要求面试者不仅对 Java 基础知识熟悉,更重要的是要了解内存模型. Java 对象模型 HotSpot JVM 使用名为 oops (Ordi ...
- JavaSwing 船只停靠管理可视化(五)
JavaSwing 船只停靠管理可视化(一) JavaSwing 船只停靠管理可视化(二) JavaSwing 船只停靠管理可视化(三) JavaSwing 船只停靠管理可视化(四) JavaSwin ...
- Spring Data JPA简介 Spring Data JPA特点
Spring Data JPA 是Spring基于ORM框架.JPA规范的基础上封装的一套JPA 应用框架,底层使用了Hibernate 的JPA技术实现,可使开发者用极简的代码即可实现对数据的访问和 ...
- 5.从零开始创建一个QT窗口按钮
如何创建一个QT项目 如何创建一个QT项目 1.创建新项目 2.配置选择 3.增加按钮 4.按钮和窗体的大小标签图标设置 5.信号与槽 6.自定义信号与槽 代码 1.创建新项目 点击文件->新建 ...
- linux中的dmesg命令以及确定进程是否被系统主动kill
linux中的dmesg命令以及确定进程是否被系统主动kill Feb 21, 2017 | java | 185 Hits 近期发现线上项目的进程莫名其妙的就不见了,也没有崩溃日志,就怀疑是被操作系 ...
- Base 128 Varints 编码(压缩算法)
Base 128 Varint可以说是一种编码方式,也可以说是一种压缩算法.这种压缩算法是用来压缩数字的传输的,压缩的依据是基于一个现实:越小的数字,越经常使用 我们来看看一个例子: 如果我们要网络传 ...
- VScode中配置C++运行环境
目录 VScode中配置C++运行环境 1. 哪些插件 2. 配置开始 3. 编写代码并运行 VScode中配置C++运行环境 关于安装mingw的教程,网络上已经有很多了,这里不再赘述,下面就看VS ...