java - 在没有 Java Mail API 或任何第三方 API 的情况下用 Java 编写 SMTP 客户端
问题描述
我在问这个问题,我感到非常尴尬。我在不使用 Java MAIL API 或任何其他第三方加密库的情况下实现 SMTP 客户端,无论是否开源,因为我不喜欢第三方 API 并希望按照我的方式做事。我知道这很傲慢,但我就是这样。所以,到目前为止我有这个: -
import java.net.Socket;
import java.util.Scanner;
import java.util.Base64;
public class SocketSample
{
public static void main(String[] args) throws Exception
{
Socket socket = null;
InputStream in = null;
OutputStream out = null;
String uid = Base64.getEncoder().encodeToString("xyz@gmail.com".getBytes());
String pwd = Base64.getEncoder().encodeToString("abc123".getBytes());
System.out.println(uid);
System.out.println(pwd);
//char ans = '\0';
Scanner scanner = new Scanner(System.in);
System.out.print("Enter host: ");
String host = scanner.nextLine();
System.out.print("Enter port: ");
int port = Integer.parseInt(scanner.nextLine());
socket = new Socket();
socket.connect(new InetSocketAddress(host, port));
if (socket.isConnected())
{
System.out.println("Socket connected.");
out = socket.getOutputStream();
String command = "HELO " + host + "\r\n";
byte[] data = command.getBytes();
out.write(data);
out.flush();
//
in = socket.getInputStream();
int c = '\0';
while (c != -1)
{
c = in.read();
System.out.print((char) c);
}
//
command = "STARTTLS\r\n";
data = command.getBytes();
out.write(data);
out.flush();
c = '\0';
while(c != -1)
{
c = in.read();
System.out.print((char) c);
}
/*
command = "HELO " + host + "\r\n";
data = Base64.getEncoder().encodeToString(command.getBytes()).getBytes();
out.write(data);
out.flush();
c = '\0';
while(c != -1)
{
c = in.read();
System.out.print((char) c);
}
*/
System.out.println(uid);
System.out.println(pwd);
command = "AUTH PLAIN " + uid + "\r\n";
data = command.getBytes();
out.write(data);
out.flush();
c = '\0';
while(c != -1)
{
c = in.read();
System.out.print((char) c);
}
//
command = pwd + "\r\n";
data = command.getBytes();
out.write(data);
out.flush();
c = '\0';
while (c != -1)
{
c = in.read();
System.out.print((char) c);
}
}
out.close();
in.close();
socket.close();
System.exit(0);
}
}
这卡在 STARTTLS 上,虽然我使用 base64 编码用户名和密码,但它仍然卡在那里。我在做什么错?请帮帮我。谢谢!PS:-我是Java新手。
解决方案
我建议依靠inputStream::available()
阅读内容的方法。这样,您可以创建一个辅助方法,例如
private static String readResponse(InputStream inputStream) throws IOException {
int c;
StringBuilder raw = new StringBuilder();
do {
c = inputStream.read();
raw.append((char) c);
} while (inputStream.available() > 0);
return raw.toString();
}
然后替换代码块
int c = '\0';
while (c != -1) {
c = in.read();
System.out.print((char) c);
}
上System.out.println(readResponse(in));
。
这样,您将继续执行STARTTLS命令,但我不确定您是否应该发送它,因为您自己使用普通 Sockets 实现的 TLS 不是您想做的家庭任务。
推荐阅读
- spring - 在 SftpOutboundGateway 上启动 GET 时出现 SpelEvaluationException
- angular - 将角度更新到版本 ^12 后,无法在 zone.d.ts 文件中重新声明块范围变量“Zone”
- amazon-web-services - AWS Jenkins 设备上没有剩余空间
- google-sheets - 根据客户电子邮件 + 日期分配整数值
- kubernetes - MinIO direct-csi 看不到 kubernetes 集群中多个节点上的驱动器
- list - 排除单词时如何使用 List.ContainsAny 达到与 Text.Contains 相同的效果?
- reactjs - 如何导出 useContext 变量而不必在每个组件上调用 useContext?
- r - 奇怪的分组条形图
- python - $lookup 在 mongodb 聚合时不起作用
- spring-boot - 如何仅在 Spring Boot 中隐藏特定配置文件的端点?