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.");
    }

STDIN の使用:

    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(またはその他)してシェルにリダイレクトを実行させる必要があります。

于 2012-06-28T18:30:05.877 に答える
2

実行してみてください{ "ksh", "-c", "mail me@example.com < " + etc }。この-cオプションは、次の引数をシェルコマンドとして解析し、リダイレクトなどを行うようシェルに明確に指示します。がないと-c、ksh はヒューリスティックに従ってコマンド ラインをどうするかを決定し、希望どおりにコマンドを実行しない可能性があります。

于 2012-06-28T19:42:47.460 に答える
1

Split into two lines, just to get better readability:

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

This will look for a program named "mail me@example.com < " + tempEmailFile.getAbsolutePath (). It will not do redirection - for that to do you have to read the output of that process yourself.

Furtermore it will not lookup the path, so you might have to specify the whole path /usr/bin/mail or whatever it is.

And you have to split command and parameters; use an Array of String instead: ("/path/to/prg", "param1", "param2", "foo=bar");

You can use redirection, if you call as program a script, like

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

It is shorter than invoking file redirection from Java yourself, more simple but you lose the ability to react sensible on different errors.

于 2012-06-28T18:44:54.220 に答える