Ričardas Mikelionis
Ričardas Mikelionis

Reputation: 113

SMTP client for Gmail on java using sockets authentication issue

I found a socket SMTP client example slightly modified for it to connect to gmail using SSLsockets, but now I don't know how to authorise account, that I am sending from. (I don't use JAVAMAIL, because this is homework)

 public class SMTP {

  public static void main(String args[]) throws IOException,
      UnknownHostException {
    String msgFile = "file.txt";
    String from = "[email protected]";
    String to = "[email protected]";
    String mailHost = "smtp.gmail.com";
    SMTP mail = new SMTP(mailHost);
    if (mail != null) {
      if (mail.send(new FileReader(msgFile), from, to)) {
        System.out.println("Mail sent.");
      } else {
        System.out.println("Connect to SMTP server failed!");
      }
    }
    System.out.println("Done.");
  }

  static class SMTP {
    private final static int SMTP_PORT = 25;

    InetAddress mailHost;

    InetAddress localhost;

    BufferedReader in;

    PrintWriter out;

    public SMTP(String host) throws UnknownHostException {
      mailHost = InetAddress.getByName(host);
      localhost = InetAddress.getLocalHost();
      System.out.println("mailhost = " + mailHost);
      System.out.println("localhost= " + localhost);
      System.out.println("SMTP constructor done\n");
    }

    public boolean send(FileReader msgFileReader, String from, String to)
        throws IOException {
      SSLSocket smtpPipe;
      InputStream inn;
      OutputStream outt;
      BufferedReader msg;
      msg = new BufferedReader(msgFileReader);
      smtpPipe = (SSLSocket) ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(InetAddress.getByName("smtp.gmail.com"), 465);
      if (smtpPipe == null) {
        return false;
      }
      inn = smtpPipe.getInputStream();
      outt = smtpPipe.getOutputStream();
      in = new BufferedReader(new InputStreamReader(inn));
      out = new PrintWriter(new OutputStreamWriter(outt), true);
      if (inn == null || outt == null) {
        System.out.println("Failed to open streams to socket.");
        return false;
      }
      String initialID = in.readLine();
      System.out.println(initialID);
      System.out.println("HELO " + localhost.getHostName());
      out.println("HELO " + localhost.getHostName());
      String welcome = in.readLine();
      System.out.println(welcome);
      System.out.println("MAIL From:<" + from + ">");
      out.println("MAIL From:<" + from + ">");
      String senderOK = in.readLine();
      System.out.println(senderOK);
      System.out.println("RCPT TO:<" + to + ">");
      out.println("RCPT TO:<" + to + ">");
      String recipientOK = in.readLine();
      System.out.println(recipientOK);
      System.out.println("DATA");
      out.println("DATA");
      String line;
      while ((line = msg.readLine()) != null) {
        out.println(line);
      }
      System.out.println(".");
      out.println(".");
      String acceptedOK = in.readLine();
      System.out.println(acceptedOK);
      System.out.println("QUIT");
      out.println("QUIT");
      return true;
    }
  }
}

Upvotes: 0

Views: 3419

Answers (2)

Akif Islam
Akif Islam

Reputation: 15

First, Make sure you have turned on 'Allow Less Secure Apps' from your Gmail. We can improve the code by ignoring the Multi-threading part by just reading the output from server. As we know from the RFC that server sends 9 lines after getting the first 'EHLO' request. So, we are just reading 9 lines with bufferedReader. Then for the next few commands, it returns only one line. So, the simplified code without multithreading will be like this :

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

public class SMTP_Simplified_v2 {
    // Credentials
    public static String user = "[email protected]";
    public static String pass = "xxxxxxxxxx";
    private static DataOutputStream dataOutputStream;
    public static BufferedReader br = null;

    public static void main(String[] args) throws Exception {
        int delay = 1000;

        String username = Base64.getEncoder().encodeToString(user.getBytes(StandardCharsets.UTF_8));
        String password = Base64.getEncoder().encodeToString(pass.getBytes(StandardCharsets.UTF_8));
        SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
        SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket("smtp.gmail.com", 465);

        br = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));

        dataOutputStream = new DataOutputStream(sslSocket.getOutputStream());

        send("EHLO smtp.gmail.com\r\n",9);
        send("AUTH LOGIN\r\n",1);
        send(username+"\r\n",1);
        send(password+"\r\n",1);
        send("MAIL FROM:<[email protected]>\r\n",1);
        send("RCPT TO:<[email protected]>\r\n",1);
        send("DATA\r\n",1);
        send("Subject: Email test\r\n",0);
        send("Email Body\r\n",0);
        send(".\r\n",0);
        send("QUIT\r\n",1);
    }
    private static void send(String s, int no_of_response_line) throws Exception
    {
        dataOutputStream.writeBytes(s);
        System.out.println("CLIENT: "+s);
        Thread.sleep(1000);

        // Just reading the number of lines the server will respond.
        for (int i = 0; i < no_of_response_line; i++) {
            System.out.println("SERVER : " +br.readLine());
        }
    }

}

Upvotes: 0

Ričardas Mikelionis
Ričardas Mikelionis

Reputation: 113

Rewrote the code. This works fine.

public class TotalTemp
{
     private static DataOutputStream dos;

     public static void main(String[] args) throws Exception
     {
          int delay = 1000;
          String user = "[email protected]";
          String pass = "xxxxxxxx11";
          String username = Base64.encodeBase64String(user.getBytes(StandardCharsets.UTF_8));
          String password = Base64.encodeBase64String(pass.getBytes(StandardCharsets.UTF_8));    

          SSLSocket sock = (SSLSocket)((SSLSocketFactory)SSLSocketFactory.getDefault()).createSocket("smtp.gmail.com", 465);
//          Socket sock = new Socket("smtp.gmail.com", 587);
          final BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
          (new Thread(new Runnable()
          {
               public void run()
               {
                    try
                    {
                         String line;
                         while((line = br.readLine()) != null)
                              System.out.println("SERVER: "+line);
                    }
                    catch (IOException e)
                    {
                         e.printStackTrace();
                    }
               }
          })).start();
          dos = new DataOutputStream(sock.getOutputStream());

          send("EHLO smtp.gmail.com\r\n");
          Thread.sleep(delay);
          send("AUTH LOGIN\r\n");
          Thread.sleep(delay);
          send(username + "\r\n");
          Thread.sleep(delay);
          send(password + "\r\n");
          Thread.sleep(delay);
          send("MAIL FROM:<[email protected]>\r\n");
          //send("\r\n");
          Thread.sleep(delay);
          send("RCPT TO:<[email protected]>\r\n");
          Thread.sleep(delay);
          send("DATA\r\n");
          Thread.sleep(delay);
          send("Subject: Email test\r\n");
          Thread.sleep(delay);
          send("Test 1 2 3\r\n");
          Thread.sleep(delay);
          send(".\r\n");
          Thread.sleep(delay);
          send("QUIT\r\n");
     }

     private static void send(String s) throws Exception
     {
          dos.writeBytes(s);
          System.out.println("CLIENT: "+s);
     }
}

Upvotes: 2

Related Questions