在Linux上调用Linux的"mailx"通过Java代码:消息文本始终包含在附件中 [英] Calling Linux's "mailx" through java code: message-text always goes into attachment

查看:72
本文介绍了在Linux上调用Linux的"mailx"通过Java代码:消息文本始终包含在附件中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于我的SMTP提供程序每天限制发送的电子邮件数量,因此我编写了Java代码来调用Linux系统的"mailx",因此我的Java程序正在运行.

Since my SMTP provider has limit on number of emails that can be sent in a day, I wrote a Java code to call the "mailx" of Linux system, my java-program is running on.

这是代码:

package sys.cmd;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class IntermediateJavaLinuxMailX {

    public static void main(String[]args) throws IOException{
        email(
                new ArrayList<String>(){{
                    add("myemailid@myserver.com");
                    add("myothermailid@otherserver.com");
                }},
                "Error Message",
                "Hello World!\r\n This is message"
        );
    }

    public static void email(
            List<String>toEmailIds,
            String subject,
            String msgText
            ) throws IOException{
        String toEmails = toString(toEmailIds);
        String[]args=new String[]{"/bin/sh" , "-c", "mailx -s \""+subject+"\" "+toEmails};
        System.out.println("The command for bash is: "+args[2]);
        Process proc= Runtime.getRuntime().exec(args);
        OutputStream o = proc.getOutputStream();//probable output for text
        InputStream i = new ByteArrayInputStream(msgText.getBytes());//probable input for message-text
        read2end(i, o);
        o.close();
    }

    private static String toString(List<String> toEmailIds) {
        StringBuilder sb= new StringBuilder();
        for(String toEmailId:toEmailIds){
            sb.append(toEmailId).append(' ');
        }
        return sb.toString();
    }

    private static void read2end(InputStream i, OutputStream o) throws IOException {
        byte[]b=new byte[1000];
        for(int a=0;(a=i.read(b))>-1;)
            o.write(b, 0, a);
        i.close();
    }

}

问题是:接收方收到的电子邮件中,文本不在消息正文中,而是在名为"noname"的附件文件中.

The problem is: The email received on the recipients side, the text is not in the message-body, but it is in an attachment-file named "noname".

问题是:如何使msgText中的字符串出现在电子邮件的邮件正文中.

The question is: How can I make the string in msgText appear in email's message-body.

添加我到目前为止所做的另一件事:

Adding one more thing I did so far:

我编写了另一个代码,该代码使用临时文件来存储消息文本&然后使用文件重定向(<)添加消息文本&它给出了预期的结果.但这是一种间接的方式.有直通车吗?这是另一个代码:

I wrote another code, that uses temporary files for storing message-text & then uses file-redirection (<) for adding message-text & it gives desired result. But that is an indirect way. Is there any direct-way? Here is that another code:

    public static void email(
            List<String>toEmailIds,
            List<String>ccEmailIds,
            List<String>bccEmailIds,
            String subject,
            byte[][]attachContents,
            String messageText
            ) throws IOException{
        String toEmails=toString(" " , toEmailIds,' ');
        String ccEmails=notEmpty(ccEmailIds)?toString(" -c ", ccEmailIds,','):"";
        String bcEmails=notEmpty(bccEmailIds)?toString(" -b ", bccEmailIds,','):"";
        String recip=bcEmails+ccEmails+toEmails;
        String[]attachmentTempFiles=new String[notEmpty(attachContents)?attachContents.length:0];
        String attachFilePaths="";
        for(int x = 0;x<attachmentTempFiles.length;++x){
            String attachTempPath = "/path/temp/attach_"+x+".file";
            byteArray2File(attachContents[x],attachTempPath);
            attachmentTempFiles[x]=" -a "+attachTempPath;
            attachFilePaths+=attachmentTempFiles[x];
        }
        String msgTxtTempFilePath="/path/temp/msg.txt";
        byteArray2File(messageText.getBytes(), msgTxtTempFilePath);
        msgTxtTempFilePath=" < "+msgTxtTempFilePath;
        String mailxCommand = "mailx " + attachFilePaths + " -s \"" + subject +"\" "+ recip + msgTxtTempFilePath;
        Runtime.getRuntime().exec(new String[]{"/bin/sh" , "-c", mailxCommand});
    }

    private static void byteArray2File(byte[] bs, String path) throws IOException {
        FileOutputStream fos=new FileOutputStream(path);
        ByteArrayInputStream bais=new ByteArrayInputStream(bs);
        read2end(bais, fos);
        fos.close();
    }

    private static boolean notEmpty(byte[][] bs) {
        return bs!=null && bs.length>0;
    }

    private static boolean notEmpty(List<String> strings) {
        return strings!=null && !strings.isEmpty();
    }

    private static String toString(String pre, List<String> toEmailIds,char separator) {
        StringBuilder sb= new StringBuilder(pre);
        for(String toEmailId:toEmailIds){
            sb.append(toEmailId).append(separator);
        }
        return sb.substring(0,sb.length()-1);
    }

    private static void read2end(InputStream i, OutputStream o) throws IOException {
        byte[]b=new byte[1000];
        for(int a=0;(a=i.read(b))>-1;)
            o.write(b, 0, a);
        i.close();
    }


-编辑-在@Serge Ballesta的评论之后添加:


--Edit-- Added after @Serge Ballesta's comment:

嗯,我尝试在Google上搜索,发现通过管道传递到Linux mailx的纯文本文件变为"Content-Type:application/octet-stream"(附件).您的问题是否相同?确定可以控制吗?收到的邮件的标题?"

"Hmm, I tried googling around and found Plain text file pipelined to Linux mailx turns to "Content-Type: application/octet-stream" (an attachment). Could your problem be the same ? To be sure could you control the headers of the received messages ?"

此代码也具有相同的效果:

This code too had same effect:

        email(
                new ArrayList<String>(){{add("user_abc@mail1.com");add("person-xyz@mailer2.com");}},
                "Error Message",
                "Content-Type: text/plain; charset=us-ascii\r\n" +
                "Content-Disposition: inline\r\n\r\n" +
                "Hello World!\r\n" +
                "This is message.\r\n\r\n\r\n"
        );

仍然,所有消息文本都放入名为"noname"的附件中.

Still, all the message text goes into an attachment named "noname".

推荐答案

用正确的解决方案替换了愚蠢的东西

EDIT : Replaced stupid things by a correct solution

在大多数Linux发行版中找到的mailx命令是​​传家宝mailx .它比原始的BSD mailx做更多的事情,并且如果其中包含任何不可打印的字符 *,则会自动对其输入进行编码.

The mailx command found in the majority of Linux distribution is heirloom mailx. It does much more things than the original BSD mailx and automatically encodes its input if there are any non printable characters in it*.

这里的问题是,它认为\r字符是非标准字符,因此将以下标头添加到邮件中:

The problem here is that it consideres that the \r characters are non standards and so it adds the following headers to the mail :

Content-Type: application/octet-stream
Content-Transfert-Encoding: base64

,邮件的文本有效地进行了64位编码.这不是真正的附件,但是许多邮件阅读器将此类邮件视为带有未命名附件的空正文.

and the text of the mail is effectively base 64 encoded. It is not a true attachement, but many mail readers treat such mails as an empty body with an unnamed attached file.

因此解决方案是从邮件正文中删除所有\r.

So the solution is to remove all the \r from the body of the mail.

实际上,如果您的LANG环境变量声明的语言环境可以使用非7位字符(éèûôüö...)mailx似乎足够聪明,可以声明扩展的字符集(fr语言环境为ISO-8859-1)并进行带引号的可打印编码.因此,即使邮件中包含(至少是西欧)非7位ASCII字符(如果没有控制字符),也应正常发送邮件.

In fact, if your LANG environment variable declares a locale that can use non 7 bits chars (éèûôüö ...) mailx seems to be clever enough to declare an extended charset (ISO-8859-1 for fr locale) and to do quoted-printable encoding. So even with (at least west european) non 7bits ASCII characters in the message, provided there are no control chararacters, the mail should be sent normally.

最后的解决方法是不使用mailx而是直接使用sendmail.

The last chance solution would be not to use mailx and directly use sendmail.

这篇关于在Linux上调用Linux的"mailx"通过Java代码:消息文本始终包含在附件中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆