1

我正在 HP-UX 机器上从控制台运行 java 应用程序。在其中,我生成一些报告,压缩它们,然后通过电子邮件发送它们。一切正常,除了电子邮件。

我正在使用邮件二进制文件从命令行发送邮件。由于它是 HP-UX,它与标准的 GNU sendmail 有点不同。

这是我用来发送邮件的代码:

    public static void EmailReports(String[] recipients, String reportArchive, String subject){
        SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy");
        String today = dateFormat.format(new Date());

        File tempEmailFile;
        BufferedWriter emailWriter;
        try {
            tempEmailFile = File.createTempFile("report_email_" + today, "msg");
            emailWriter = new BufferedWriter(new FileWriter(tempEmailFile));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Failed to send email. Could not create temporary file.");
            return;
        }

        try {
            emailWriter.write("SUBJECT: " + subject + "\n");
            emailWriter.write("FROM: " + FROM + "\n");
            emailWriter.write(BODY + "\n"); 
            emailWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Failed to send email. Could not write to temporary file.");
        }

        //read the archive in
        try {
            FileInputStream archiveIS = new FileInputStream(new File(reportArchive));
            OutputStream archiveEncoder = MimeUtility.encode(new FileOutputStream(tempEmailFile, true), "uuencode", Zipper.getArchiveName(reportArchive));

            //read archive
            byte[] buffer = new byte[archiveIS.available()];    //these should never be more than a megabyte or two, so storing it in memory is no big deal.
            archiveIS.read(buffer);

            //encode archive
            archiveEncoder.write(buffer);

            //close both
            archiveIS.close();
            archiveEncoder.close();

        } catch (FileNotFoundException e) {
            System.out.println("Failed to send email. Could not find archive to email.");
            e.printStackTrace();
        } catch (MessagingException e) {
            System.out.println("Failed to send email. Could not encode archive.");
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Failed to send email. Could not encode archive.");
        }
        System.out.println("Sending '" + subject + "' email.");     

        try {
            Process p = Runtime.getRuntime().exec("mail me@example.com < " + tempEmailFile.getAbsolutePath());
            System.out.println("mail me@example.com < " + tempEmailFile.getAbsolutePath());

            StringBuffer buffer = new StringBuffer();
            while(p.getErrorStream().available() > 0){
                buffer.append((char) p.getErrorStream().read());
            }

            System.out.println("STDERR: " + buffer.toString());

            buffer = new StringBuffer();
            while(p.getInputStream().available() > 0){
                buffer.append((char) p.getInputStream().read());
            }

            System.out.println("STDOUT: " + buffer.toString());
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Failed to send email. Could not get access to the shell.");
        }
    }

当我运行程序并发送电子邮件时,我收到一封空白电子邮件,没有主题、没有正文、没有附件,它来自 HP-UX 框中的 user@hostname,而不是来自FROM.

但是,当我运行它运行的同一行时(请参阅我调用 exec 后打印出的命令),我会从正确的用户那里收到正确的电子邮件,其中包含主题、正文和附件。

STDOUT 和 STDERR 都是空的。就好像我正在向邮件发送一个空白文件,但是当我在调用 exec 之前打印文件时,它就在那里。

这里发生了什么?

编辑:尝试:

使用 Ksh:

    try {
        String cmd = "mail me@example.com.com < " + tempEmailFile.getAbsolutePath();            
        Runtime.getRuntime().exec(new String[] {"/usr/bin/ksh", cmd});

    } catch (IOException e) {
        e.printStackTrace();
        System.out.println("Failed to send email. Could not get access to the shell.");
    }

使用标准输入:

    try {
        System.out.println("mail me@example.com < " + tempEmailFile.getAbsolutePath());

        Process p = Runtime.getRuntime().exec("mail me@example.com ");

        FileInputStream inFile = new FileInputStream(tempEmailFile);
        byte[] byteBuffer = new byte[inFile.available()];
        inFile.read(byteBuffer);
        p.getOutputStream().write(byteBuffer);

        inFile.close();
        p.getOutputStream().close();

        StringBuffer buffer = new StringBuffer();
        while(p.getErrorStream().available() > 0){
            buffer.append((char) p.getErrorStream().read());
        }

        System.out.println("STDERR: " + buffer.toString());

        buffer = new StringBuffer();
        while(p.getInputStream().available() > 0){
            buffer.append((char) p.getInputStream().read());
        }

        System.out.println("STDOUT: " + buffer.toString());
    } catch (IOException e) {
        e.printStackTrace();
        System.out.println("Failed to send email. Could not get access to the shell.");
    }
4

3 回答 3

2

我强烈怀疑问题是重定向。这通常由外壳处理 - 这里没有外壳。

您需要正常执行该进程,然后获取该进程的标准输入流并从 Java 写入,或者可能更简单)运行/bin/sh(或其他)以让 shell 进行重定向。

于 2012-06-28T18:30:05.877 回答
2

尝试执行{ "ksh", "-c", "mail me@example.com < " + etc }。该-c选项专门告诉外壳程序将下一个参数解析为带有可能重定向等的外壳程序命令。如果没有-c, ksh 会遵循启发式方法来决定如何处理其命令行,并且它可能不会以您希望的方式运行命令。

于 2012-06-28T19:42:47.460 回答
1

分成两行,以获得更好的可读性:

        String cmd = "mail me@example.com < " + tempEmailFile.getAbsolutePath () ;
        Process p = Runtime.getRuntime().exec (cmd);

这将寻找一个名为"mail me@example.com < " + tempEmailFile.getAbsolutePath (). 它不会进行重定向 - 为此,您必须自己阅读该过程的输出。

此外,它不会查找路径,因此您可能必须指定整个路径 /usr/bin/mail 或其他任何路径。

你必须拆分命令和参数;改用字符串数组: ("/path/to/prg", "param1", "param2", "foo=bar");

如果您将脚本作为程序调用,则可以使用重定向,例如

String cmd = "/usr/bin/mail me@example.com < " + tempEmailFile.getAbsolutePath () ;
String cmdarr = new String [] {"/bin/bash", "-c", cmd}; 
Process p = Runtime.getRuntime().exec (cmdarr);

它比自己从 Java 调用文件重定向更短,更简单,但是您失去了对不同错误做出明智反应的能力。

于 2012-06-28T18:44:54.220 回答