简体   繁体   English

Java Runtime.exec()不从命令行发送电子邮件

[英]Java Runtime.exec() not sending emails as from the command line

I'm creating a java application and one of the features I would like to add is sending a generated email out to users. 我正在创建一个java应用程序,我想添加的一个功能是将生成的电子邮件发送给用户。 I have set up mail on my Macbook and I can send emails from the command line just fine. 我在Macbook上设置了邮件,我可以从命令行发送电子邮件。 I'm having an issue sending emails when I call runtime.exec(). 我在调用runtime.exec()时发送电子邮件时遇到问题。 Anyone have any idea why it will not execute and send the emails? 任何人都知道为什么它不会执行和发送电子邮件?

Runtime runtime = Runtime.getRuntime();

try {
    runtime.exec("echo This is the body | mail -s Subject -F myemail@gmail.com");
}
catch ( Exception e ) {

    // TODO Auto-generated catch block
    e.printStackTrace();
}

I don't get any errors and everything compiles fine. 我没有得到任何错误,一切都编译得很好。 I just don't get any emails sent out. 我只是没有收到任何电子邮件。 If anyone could hel it would be much appreciated thanks. 如果有人能够帮助,将非常感谢谢谢。

Runtime.exec(String) does not execute the entire string by pasting it into a UNIX shell and running it. Runtime.exec(String)不会通过将其粘贴到UNIX shell并运行它来执行整个字符串。 This is because it's a huge security flaw. 这是因为它是一个巨大的安全漏洞。

Imagine you did this: 想象一下你这样做了:

runtime.exec("Hello "+name+" | mail ...");

I could then set name to ; rm -rf /*; echo 然后我可以设置name ; rm -rf /*; echo ; rm -rf /*; echo ; rm -rf /*; echo or && cat /etc/passwd , or some other shell injection code. ; rm -rf /*; echo&& cat /etc/passwd ,或其他一些shell注入代码。

So, Java is breaking up your command into parts : 因此, Java正在将您的命令分解为多个部分

More precisely, the command string is broken into tokens using a StringTokenizer created by the call new StringTokenizer(command) with no further modification of the character categories. 更确切地说,命令字符串使用由调用new StringTokenizer(命令)创建的StringTokenizer分解为标记,而不进一步修改字符类别。 The tokens produced by the tokenizer are then placed in the new string array cmdarray, in the same order. 然后,由标记化器生成的标记以相同的顺序放置在新的字符串数组cmdarray中。

Ultimately, you are running the echo command alone, with parameters such as | 最终,您将单独运行echo命令,其参数如| and mail . mail The echo command will just print these out to standard output, which you don't collect. echo命令只会将这些输出打印到您不收集的标准输出。 It will never invoke the mail command. 它永远不会调用mail命令。

You shouldn't use the mail command to send mail from Java, due to the security risks involved. 由于涉及安全风险,您不应使用mail命令从Java发送邮件。 You should use the JavaMail package which provides a safe and convenient API for sending mail. 您应该使用JavaMail包,它提供了一个安全方便的API来发送邮件。 The UNIX mail command works by connecting to a sendmail daemon running on the local machine on port 25, and JavaMail can do this too. UNIX mail命令通过连接到端口25上本地计算机上运行的sendmail守护程序来工作,JavaMail也可以这样做。

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;

public class SendMail {
    public static sendMail(String from, String to, String subject, String body)
        throws MessagingException
    {
        final Properties p = new Properties();
        p.put("mail.smtp.host", "localhost");
        final Message msg = new MimeMessage(Session.getDefaultInstance(p));
        msg.setFrom(new InternetAddress(from));
        msg.addRecipient(RecipientType.TO, new InternetAddress(to));
        msg.setSubject(subject);
        msg.setText(body);
        Transport.send(msg);
    }
}

Why don't you use JavaMail ? 你为什么不使用JavaMail

Example usage: 用法示例:

private boolean sendMail(String host, String port, String user, String password,  List<String> toList, String htmlBody, String subject) {
    Properties props = System.getProperties();
    props.put("mail.smtp.user", user);
    props.put("mail.smtp.password", password);
    props.put("mail.smtp.host", host);
    props.put("mail.smtp.port", port);
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.EnableSSL.enable", "true");

    Session session = Session.getInstance(props, null);

    MimeMessage message = new MimeMessage(session);
    try {

        message.setFrom(new InternetAddress(user));

        // To get the array of addresses
        for (String to : toList) {
            message.addRecipient(Message.RecipientType.TO,
                    new InternetAddress(to));
        }

        message.setSubject(subject);
        message.setContent(htmlBody, "text/html");

        Transport transport = session.getTransport("smtp");
        try {
            transport.connect(host, user, password);
            transport.sendMessage(message, message.getAllRecipients());
        } finally {
            transport.close();
        }

    } catch (Exception e) {
        return false;
    } 
    return true;
}

Because you are not spawning a shell and the | 因为你没有产生shell和| is a shell feature. 是一个shell功能。 An example that works: 一个有效的例子:

Create a shell script and pass a command array to exec(). 创建一个shell脚本并将命令数组传递给exec()。

class Test {
  public static void main(String[] args) {
    try {
      Runtime runtime = Runtime.getRuntime();
      String[] cmd = { "sh", "send.sh", "This is the body", "Subject", "myemail@gmail.com"};
      runtime.exec(cmd);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

Shell script: Shell脚本:

echo $1 | mail -s $2 -F $3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM