Не могу отправить сообщение - SMTP - PullRequest
1 голос
/ 21 апреля 2020

Я нахожусь в процессе создания SMTP-клиента, где я могу отправить сообщение по почте. У меня возникает проблема - я использовал разные почтовые идентификаторы и порты, но не могу отправить его на работу.

Я, например, пытался использовать hotmail.com (live.com) и gmail.com.

Google / Gmail: - Почтовый сервер: smtp.gmail.com - Порт: 587

И не повезло. Кто-то, кто может направить меня и сказать мне, что я делаю неправильно и как ввести и использовать необходимую информацию?

Вот коды:

SMTPConnection. java

import java.net.*;
import java.io.*;
import java.util.*;
/**Open an SMTP connection to a remote machine and send one mail.*/
public class SMTPConnection {
/* The socket to the server */
public Socket connection;

/* Streams for reading and writing the socket */
public BufferedReader fromServer;
public DataOutputStream toServer;

/* Just to make it look nicer */
private static final int SMTP_PORT = 25;
private static final String CRLF = "\r\n";

/* Are we connected? Used in close() to determine what to do. */
private boolean isConnected = false;

/*
 * Create an SMTPConnection object. Create the socket and the associated
 * streams. Send HELO-command and check for errors.
 */
public SMTPConnection(Envelope envelope) throws IOException {
    connection = new Socket(envelope.DestAddr, SMTP_PORT);
    fromServer = new BufferedReader(new InputStreamReader(
            connection.getInputStream()));
    toServer = new DataOutputStream(connection.getOutputStream());

    String reply = fromServer.readLine();
    if (parseReply(reply) != 220) {
        System.out.println("Error in connect.");
        System.out.println(reply);
        return;
    }
    String localhost = (InetAddress.getLocalHost()).getHostName();
    try {
        sendCommand("HELO " + localhost, 250);
    } catch (IOException e) {
        System.out.println("HELO failed. Aborting.");
        return;
    }
    isConnected = true;
}

/*
 * Send the message. Simply writes the correct SMTP-commands in the correct
 * order. No checking for errors, just throw them to the caller.
 */
public void send(Envelope envelope) throws IOException {
    sendCommand("MAIL FROM:<" + envelope.Sender + ">", 250);
    sendCommand("RCPT TO:<" + envelope.Recipient + ">", 250);
    sendCommand("DATA", 354);
    sendCommand(envelope.Message.toString() + CRLF + ".", 250);
}

/*
 * Close the connection. Try to send QUIT-commmand and then close the
 * socket.
 */
public void close() {
    isConnected = false;
    try {
        sendCommand("QUIT", 221);
        connection.close();
    } catch (IOException e) {
        System.out.println("Unable to close connection: " + e);
        isConnected = true;
    }
}

/*
 * Send an SMTP command to the server. Check for reply code. Does not check
 * for multiple reply codes (required for RCPT TO).
 */
private void sendCommand(String command, int rc) throws IOException {
    String reply = null;

    toServer.writeBytes(command + CRLF);
    reply = fromServer.readLine();
    if (parseReply(reply) != rc) {
        System.out.println("Error in command: " + command);
        System.out.println(reply);
        throw new IOException();
    }

}

/* Parse the reply line from the server. Returns the reply code. */
private int parseReply(String reply) {
    StringTokenizer parser = new StringTokenizer(reply);
    String replycode = parser.nextToken();
    return (new Integer(replycode)).intValue();
}

/* Destructor. Closes the connection if something bad happens. */
protected void finalize() throws Throwable {
    if (isConnected) {
        close();
    }
    super.finalize();
}
}

MailClient. java

import java.io.*;
import java.awt.*;
import java.awt.event.*;
/**A simple mail client with a GUI for sending mail.*/
public class MailClient extends Frame {
private static final long serialVersionUID = 1L;
/* The stuff for the GUI. */
private Button btSend = new Button("Send");
private Button btClear = new Button("Clear");
private Button btQuit = new Button("Quit");
private Label serverLabel = new Label("Local mailserver:");
private TextField serverField = new TextField("", 40);
private Label fromLabel = new Label("From:");
private TextField fromField = new TextField("", 40);
private Label toLabel = new Label("To:");
private TextField toField = new TextField("", 40);
private Label subjectLabel = new Label("Subject:");
private TextField subjectField = new TextField("", 40);
private Label messageLabel = new Label("Message:");
private TextArea messageText = new TextArea(10, 40);

/**
 * Create a new MailClient window with fields for entering all the relevant
 * information (From, To, Subject, and message).
 */
@SuppressWarnings("deprecation")
public MailClient() {
    super("Java Mailclient");

    /*
     * Create panels for holding the fields. To make it look nice, create an
     * extra panel for holding all the child panels.
     */
    Panel serverPanel = new Panel(new BorderLayout());
    Panel fromPanel = new Panel(new BorderLayout());
    Panel toPanel = new Panel(new BorderLayout());
    Panel subjectPanel = new Panel(new BorderLayout());
    Panel messagePanel = new Panel(new BorderLayout());
    serverPanel.add(serverLabel, BorderLayout.WEST);
    serverPanel.add(serverField, BorderLayout.CENTER);
    fromPanel.add(fromLabel, BorderLayout.WEST);
    fromPanel.add(fromField, BorderLayout.CENTER);
    toPanel.add(toLabel, BorderLayout.WEST);
    toPanel.add(toField, BorderLayout.CENTER);
    subjectPanel.add(subjectLabel, BorderLayout.WEST);
    subjectPanel.add(subjectField, BorderLayout.CENTER);
    messagePanel.add(messageLabel, BorderLayout.NORTH);
    messagePanel.add(messageText, BorderLayout.CENTER);
    Panel fieldPanel = new Panel(new GridLayout(0, 1));
    fieldPanel.add(serverPanel);
    fieldPanel.add(fromPanel);
    fieldPanel.add(toPanel);
    fieldPanel.add(subjectPanel);

    /*
     * Create a panel for the buttons and add listeners to the buttons.
     */
    Panel buttonPanel = new Panel(new GridLayout(1, 0));
    btSend.addActionListener(new SendListener());
    btClear.addActionListener(new ClearListener());
    btQuit.addActionListener(new QuitListener());
    buttonPanel.add(btSend);
    buttonPanel.add(btClear);
    buttonPanel.add(btQuit);

    /* Add, pack, and show. */
    add(fieldPanel, BorderLayout.NORTH);
    add(messagePanel, BorderLayout.CENTER);
    add(buttonPanel, BorderLayout.SOUTH);
    pack();
    show();
}

static public void main(String argv[]) {
    new MailClient();
}

/* Handler for the Send-button. */
class SendListener implements ActionListener {
    public void actionPerformed(ActionEvent event) {
        System.out.println("Sending mail");

        /* Check that we have the local mailserver */
        if ((serverField.getText()).equals("")) {
            System.out.println("Need name of local mailserver!");
            return;
        }

        /* Check that we have the sender and recipient. */
        if ((fromField.getText()).equals("")) {
            System.out.println("Need sender!");
            return;
        }
        if ((toField.getText()).equals("")) {
            System.out.println("Need recipient!");
            return;
        }

        /* Create the message */
        Message mailMessage = new Message(fromField.getText(),
                toField.getText(), subjectField.getText(),
                messageText.getText());

        /*
         * Check that the message is valid, i.e., sender and recipient
         * addresses look ok.
         */
        if (!mailMessage.isValid()) {
            return;
        }

        /*
         * Create the envelope, open the connection and try to send the
         * message.
         */
        try {
            Envelope envelope = new Envelope(mailMessage,
                    serverField.getText());

            SMTPConnection connection = new SMTPConnection(envelope);
            connection.send(envelope);
            connection.close();
        } catch (IOException error) {
            System.out.println("Sending failed: " + error);
            return;
        }
        System.out.println("Mail sent succesfully!");
    }
}

/* Clear the fields on the GUI. */
class ClearListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Clearing fields");
        fromField.setText("");
        toField.setText("");
        subjectField.setText("");
        messageText.setText("");
    }
}

/* Quit. */
class QuitListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        System.exit(0);
    }
}
}

Сообщение. java

import java.util.*;
import java.text.*;
/*Mail message.*/
public class Message {
/* The headers and the body of the message. */
public String Headers;
public String Body;

/*
 * Sender and recipient. With these, we don't need to extract them from the
 * headers.
 */
private String From;
private String To;

/* To make it look nicer */
private static final String CRLF = "\r\n";

/*
 * Create the message object by inserting the required headers from RFC 822
 * (From, To, Date).
 */
public Message(String from, String to, String subject, String text) {
    /* Remove whitespace */
    From = from.trim();
    To = to.trim();
    Headers = "From: " + From + CRLF;
    Headers += "To: " + To + CRLF;
    Headers += "Subject: " + subject.trim() + CRLF;

    /*
     * A close approximation of the required format. Unfortunately only GMT.
     */
    SimpleDateFormat format = new SimpleDateFormat(
            "EEE, dd MMM yyyy HH:mm:ss 'GMT'");
    String dateString = format.format(new Date());
    Headers += "Date: " + dateString + CRLF;
    Body = text;
}

/* Two functions to access the sender and recipient. */
public String getFrom() {
    return From;
}

public String getTo() {
    return To;
}

/*
 * Check whether the message is valid. In other words, check that both
 * sender and recipient contain only one @-sign.
 */
public boolean isValid() {
    int fromat = From.indexOf('@');
    int toat = To.indexOf('@');

    if (fromat < 1 || (From.length() - fromat) <= 1) {
        System.out.println("Sender address is invalid");
        return false;
    }
    if (toat < 1 || (To.length() - toat) <= 1) {
        System.out.println("Recipient address is invalid");
        return false;
    }
    if (fromat != From.lastIndexOf('@')) {
        System.out.println("Sender address is invalid");
        return false;
    }
    if (toat != To.lastIndexOf('@')) {
        System.out.println("Recipient address is invalid");
        return false;
    }
    return true;
}

/* For printing the message. */
public String toString() {
    String res;

    res = Headers + CRLF;
    res += Body;
    return res;
}
}

Конверт. java

import java.net.*;
import java.util.*;
/*SMTP envelope for one mail message.*/
public class Envelope {
/* SMTP-sender of the message (in this case, contents of From-header. */
public String Sender;

/* SMTP-recipient, or contents of To-header. */
public String Recipient;

/* Target MX-host */
public String DestHost;
public InetAddress DestAddr;

/* The actual message */
public Message Message;

/* Create the envelope. */
public Envelope(Message message, String localServer)
        throws UnknownHostException {
    /* Get sender and recipient. */
    Sender = message.getFrom();
    Recipient = message.getTo();

    /*
     * Get message. We must escape the message to make sure that there are
     * no single periods on a line. This would mess up sending the mail.
     */
    Message = escapeMessage(message);

    /*
     * Take the name of the local mailserver and map it into an InetAddress
     */
    DestHost = localServer;
    try {
        DestAddr = InetAddress.getByName(DestHost);
    } catch (UnknownHostException e) {
        System.out.println("Unknown host: " + DestHost);
        System.out.println(e);
        throw e;
    }
    return;
}

/*
 * Escape the message by doubling all periods at the beginning of a line.
 */
private Message escapeMessage(Message message) {
    String escapedBody = "";
    String token;
    StringTokenizer parser = new StringTokenizer(message.Body, "\n", true);

    while (parser.hasMoreTokens()) {
        token = parser.nextToken();
        if (token.startsWith(".")) {
            token = "." + token;
        }
        escapedBody += token;
    }
    message.Body = escapedBody;
    return message;
}

/* For printing the envelope. Only for debug. */
public String toString() {
    String res = "Sender: " + Sender + '\n';
    res += "Recipient: " + Recipient + '\n';
    res += "MX-host: " + DestHost + ", address: " + DestAddr + '\n';
    res += "Message:" + '\n';
    res += Message.toString();

    return res;
}
}

И .. после запуска программы выше я получаю следующую ошибку:

Error in command: MAIL FROM:<azmibobo2650@gmail.com>
530 5.7.0 Must issue a STARTTLS command first. i17sm4367728wru.39 - gsmtp
Sending failed java.io.IOException

Кто-то, кто может помочь?

...