Java实现伪造邮件发信人

Java 专栏收录该内容
1 篇文章 0 订阅

关键词

Java、邮件、SMTP、伪造、发信人、邮箱、由……代发

效果预览

在这里插入图片描述

背景说明

作业背景

最近在做设计,设计里涉及到邮件通知功能,但是直接使用自己个人邮箱发送的话显得那啥一点,并且在Python SMTP发送邮件里发现是可以伪造邮件的,故打算把自己的邮箱“打扮”一下,将自己的设计模拟的更真实一点。可不要拿来做不好的事情哦

环境

  • Win10、Linux
  • Java8(不需要额外的jar)

参考说明

看了不少做JavaEmail的文章,基本上都是采用javax.mail.jar包做的,但是无法实现伪造发信人(这里的发信人指的是邮箱,这个包昵称是可以指定的。可能之前的setSender可以,但是我没用过,我下载的1.6.2版本的,MimeMessage对象没有setSender方法),主要参考了两篇文章(后面给出),都写的很好,我写这篇文章的目的是让朋友们多一个维度参考。下面是我参考的文章:
1.JAVA实现SMTP邮件发送
2.java发送邮件的两种实现方式(包括如何伪造发件人及其原理)
对了还有一篇:Java8 Base64 | 菜鸟教程

实现代码

喜欢图片的朋友看这个,喜欢代码的在后面
在这里插入图片描述
源代码:

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class SMTPSendMail {
    public static void main(String[] args) {
        String loginUsername = "sample@163.com"; //<- 登录邮箱,这里仅为示例
        String loginPassword = "JCTAJSNCUPEMKPZO"; //<- 16位授权密码
        String realAddressee  = "receiver@xxx.com"; //<- 收件人邮箱
        String smtpServer = "smtp.163.com"; //<- smtp服务器地址
        int port = 25;

        String b64Username = Base64.getEncoder().encodeToString(loginUsername.getBytes(StandardCharsets.UTF_8));
        String b64Password = Base64.getEncoder().encodeToString(loginPassword.getBytes(StandardCharsets.UTF_8));

        try {
            Socket socket = new Socket(smtpServer, port);
            BufferedReader bfr = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);

            //发送'helo'命令, 读取输出
            pw.println("helo " + "Stephen");
            System.out.println(bfr.readLine());

            //发送'auth login'命令
            pw.println("auth login");
            System.out.println(bfr.readLine());
            pw.println(b64Username); // 用户名base64
            System.out.println(bfr.readLine());
            pw.println(b64Password); // 授权密码base64
            System.out.println(bfr.readLine());

            //设置'mail from' 和 'rcpt to'
            pw.println("mail from:<"+loginUsername+">");
            System.out.println(bfr.readLine());
            pw.println("rcpt to:<" + realAddressee + ">");
            System.out.println(bfr.readLine());

            //设置'data'
            pw.println("data");
            System.out.println(bfr.readLine());

            /* 正文主体 */
            pw.println("subject:" + "主题什么的随随便便就好了"); // 主题
            // “伪造”发信人
            pw.println("from:" + "一方巨鳄 <xxxxxx@163.com>");  //格式:昵称 <显示的发件人邮箱>(伪发件人)
            pw.println("to:" + "管理员 <" + realAddressee + ">"); //指定收件人名称,有的smtp服务器可以把收件人显示的邮箱也改了
                                                                // 这里smtp.163.com会"554 DT:SPM"退信
            pw.println("Content-Type:text/html;charset=\"utf-8\""); // 这里采用的是html类型,可换为纯文本plain类型
            pw.println();
            String text = "<html><body><table border=\"1\"> <h1>表格</h1>" +
                    "<tr><th>姓名</th><td>理智</td></tr>" +
                    "<tr><th>性别</th><td align=\"center\">男</td></tr></table></body></html>";
            pw.println(text);
            pw.println();
            pw.println("."); //内容部分结束
            System.out.println(bfr.readLine());

            //发送结束,退出
            pw.println("rset");
            System.out.println(bfr.readLine());
            pw.println("quit");
            System.out.println(bfr.readLine());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

代码解析及输出

可以看到,上面的代码主要是pw.println()bfr.readLine(),前者主要是发命令的,而后者则是接收响应的。模拟Telnet客户端发邮件[1]。

输出
在这里插入图片描述
邮件效果在开头已给出,那是我用学校邮箱的smtp服务器发的,改了收件人显示的信息,没有被退信。

测试及避坑

  1. 我在使用smtp.163.com服务器的情况下在to:命令之后接假收件人时遇到这个
    554 DT:SPM 163 smtp10,DsCowAD3__ck_rxeJqxmBw--.19039S2 1589444132,please see
    http://mail.163.com/help/help_spam_16.htm?ip=111.58.181.219&hostid=smtp10&time=1589444132
    点进去看,是“退信代码说明”
    在这里插入图片描述
    解决办法:把图第49行的收件人改回真实收件人邮箱(上面的已改,原来的代码是pw.println("to:" + "管理员 <xxxxxx@qq.com>");实现的就是效果图)就可以了。

  2. 测试139邮箱时,一直报550 2f015ebe0b3f97a-4e9fd Mail rejected,ta没有给授权码,就是使用的登录密码,我尝试的所有办法都无法发邮件(无论是否伪造)
    在这里插入图片描述
    解决办法:暂无,劝君慎用139,或者有解决的踢我一脚谢谢

  3. 测试sina邮箱,sina邮箱是要将mail fromfrom进行匹配的,也就是无法通过这个方法进行伪造,有知道怎么做的也可以提醒我谢谢。
    在这里插入图片描述
    解决办法:我无。

  4. 测试126邮箱,给qq邮箱发邮件,第一次可以伪造(显示代发,并且有一段特殊信息回显),之后就是显示真实的邮箱地址。

  5. 目前就测试了这几个邮箱服务商,总的来说就qq、163和126可以伪造发信人,这几个邮箱开启SMTP服务的话短信是自己发的短信费是自己掏的,所以写这篇文章是含有成本在里面的(含金量杠杠的🐕)。

启示

收到邮件注意一下邮件内容,奇怪的发信人奇怪的邮箱注意查看信头,信头中的Sender一般即为真实发信人,使用一些比较知名的邮箱服务平台等,小平台的邮箱甚至某些有名的平台如某浪的邮箱可能还不会显示由……代发,比如说我测试过的临时邮箱查看伪造的邮件就没有显示真实邮件地址,这得注意信头的Sender了。

拓展阅读

1.SMTP协议详解
2.廖雪峰Python-电子邮件-SMTP发送邮件

  • 2
    点赞
  • 2
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值