Java發送帶圖表郵件

以下代碼可以複製直接使用,目前自己正在使用

發送郵件的依賴

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-email</artifactId>
    <version>1.4</version>
</dependency>

實現的原理
郵件內容是html,在郵件內容中需要帶圖的地方寫

<img src="cid:cid的值">

換成代碼就是
String cid = "1111";
StringBuilder sb = new StringBuilder();
sb.append("<h3>測試圖片發送</h3>\r\n");
sb.append("<img src=\"cid:").append(cid).append("\">");
String mailContent = sb.toString();

發送郵件的工具類,可以直接用

package com.test;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.mail.EmailAttachment;
import org.apache.commons.mail.HtmlEmail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.activation.DataSource;
import java.util.Date;

public class EmailUtil {

	private static Logger logger = LoggerFactory.getLogger(EmailUtil.class);

	/**
	 * 發送給誰
	 */
	private String toUser = "xxx";
	/**
	 * 抄送給誰
	 */
	private String ccUser = "xxx";
	/**
	 * 密送給誰
	 */
	private String bccUser = "";
	/**
	 * host
	 */
	private String host = "郵箱host";
	/**
	 * auth
	 */
	private String auth = "true";
	/**
	 * port
	 */
	private String port = "25";
	/**
	 * username
	 */
	private String username = "發送郵件的郵箱";
	/**
	 * password
	 */
	private String password = "密碼";
	/**
	 * type
	 */
	private String contentType = "UTF-8";

	public boolean sendMail(MailInfo content){
		boolean iscoorect=false;
		String[] to=toUser.contains(",")?toUser.split(","):new String[] {toUser};
		String[] cc=ccUser.contains(",")?ccUser.split(","):new String[] {ccUser};
		String[] bcc=bccUser.contains(",")?bccUser.split(","):new String[] {bccUser};
		try {
			HtmlEmail mail = new HtmlEmail();
			// 設置郵箱服務器信息
			mail.setSmtpPort(Integer.parseInt(port));
			mail.setHostName(host);
			// 設置密碼驗證器
			mail.setAuthentication(username, password);
			// 設置郵件發送者
			mail.setFrom(username);
			// 設置郵件接收者
			mail.addTo(to);
			if(StringUtils.isNoneBlank(bcc)) {
				mail.addBcc(bcc);
			}
			if(StringUtils.isNoneBlank(cc)) {
				mail.addCc(cc);
			}
			// 設置郵件編碼
			mail.setCharset(contentType);
			// 設置郵件主題
			if(StringUtils.isNoneBlank(content.subject)){
				mail.setSubject(content.subject);
			}
			// 郵件內容
			if(StringUtils.isNoneBlank(content.msg)){
				mail.setHtmlMsg(content.msg);
			}

			// 插入圖片資源
			String[] cids = content.cids;
			if(cids != null){
				DataSource[] ds = content.ds;
				for (int i = 0; i < cids.length; i++) {
					mail.embed(ds[i], cids[i]);
				}
			}

			// 創建附件
			if(StringUtils.isNotBlank(content.attachmentPath) && StringUtils.isNotBlank(content.attachmentName)){
				EmailAttachment attachment = new EmailAttachment();
				attachment.setPath(content.attachmentPath);
				attachment.setDisposition(EmailAttachment.ATTACHMENT);
				attachment.setName(content.attachmentName);
				mail.attach(attachment);
			}
			// 設置郵件發送時間
			mail.setSentDate(new Date());
			// 發送郵件
			mail.send();
			logger.info("發送成功");
			iscoorect=true;
		}catch(Exception e) {
			logger.info("發送失敗,異常:{}", e);
		}
		return iscoorect;
	}

	public static class MailInfo{
		/**
		 * 附件名稱
		 */
		public String attachmentName;
		/**
		 * 附件路徑
		 */
		public String attachmentPath;

		public String subject;
		/**
		 * html郵件內容,包涵所有的信息,上面提到的圖片內嵌的標籤也在這裏
		 */
		public String msg;

		/**
		 * 郵件中插入的圖片cid,引用方式爲   <img src=\"cid:" + cid + "\"></html>"
		 */
		public String[] cids;
		/**
		 * 郵件中插入的圖片資源,和cids一一對應
		 */
		public DataSource[] ds;
	}

}

上面的郵件工具使用的圖表生成工具。注意這個依賴的是java的生成圖片的類庫,確保運行程序的java環境中能正常初始化。如果不能用,繼續往後看。有替代的工具。反正我是本地可以用,服務器上用不了。沒有深入研究爲啥,先完成任務再說。。。

package com.test;

import brand.entity.ReportBean;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.image.WritableImage;

import javax.imageio.ImageIO;
import javax.mail.util.ByteArrayDataSource;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 生成折線圖的工具,發送郵件時插入圖片
 */
public class ChartUtils {

    /**
     * 
     * 返回的是ByteArrayDataSource類型的折線圖。大家可以根據需要擴展曲線圖的類型。
     * 注意調用時要這樣調用
     * PlatformImpl.startup(() -> {
     *
     *      ByteArrayDataSource ds = generateLineChart(xxxxxxxxxx);
     *
     *  });
     *
     *
     */
    public static ByteArrayDataSource generateLineChart(Long[] x, Long[] y, String title){
        //Defining the x axis
        NumberAxis xAxis = new NumberAxis(x[0], x[x.length - 1], 1);
        xAxis.setLabel("Minutes");

        List<XYChart.Data> l = new ArrayList<XYChart.Data>();
        long min = y[0];
        long max = 0;
        for (int i = 0; i < y.length; i++) {
            long count = y[i];
            if(count < min){
                min = count;
            }
            if(count > max){
                max = count;
            }
            l.add(new XYChart.Data(x[i], y[i]));
        }

        min = min - 10;
        //Defining the y axis
        NumberAxis yAxis = new NumberAxis(min < 0 ? 0 : min, max + 10, (max - min) / 10);
        yAxis.setLabel("count");

        //Creating the line chart
        LineChart linechart = new LineChart(xAxis, yAxis);

        //Prepare XYChart.Series objects by setting data
        XYChart.Series series = new XYChart.Series();
        series.setName(title);

        series.getData().addAll(l);

        //Setting the data to Line chart
        linechart.getData().add(series);

        //防止座標刻度不顯示
        linechart.setAnimated(false);

        //Creating a scene object
        Scene scene = new Scene(linechart, 1000, 600);

        WritableImage writableImage = new WritableImage(1000, 600);
        linechart.snapshot(new SnapshotParameters(), writableImage);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            ImageIO.write(SwingFXUtils.fromFXImage(writableImage, null), "png", bos);
        } catch (Exception s) {
            s.printStackTrace();
        }

        return new ByteArrayDataSource(bos.toByteArray(),"image/png");
    }


}

如果上面說的工具不可以,還有個工具JFreeChart
注意版本是1.0.19

<dependency>
    <groupId>org.jfree</groupId>
    <artifactId>jfreechart</artifactId>
    <version>1.0.19</version>
</dependency>

這個工具類中的示例方法返回的也是ByteArrayDataSource,和上面那種java的返回類型一樣,因此可以隨意切換。如果有其他的工具也可以擴展,很容易

package com.test;

import java.awt.*;
import java.io.*;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.general.DatasetUtilities;

import javax.mail.util.ByteArrayDataSource;

public class JFreeChartTest {

	// 這個方法自己測試過,中文也能正常顯示。代碼比較亂,大家簡單重構一下即可
    public static ByteArrayDataSource generateLineChart() {

        String[] rowKeys = {"A系列"};
        String[] colKeys = {"0:00", "1:00", "2:00", "7:00", "8:00", "9:00",
                "10:00", "11:00", "12:00", "13:00", "16:00", "20:00", "21:00",
                "23:00"};
        double[][] data = {{4, 3, 1, 1, 1, 1, 2, 2, 2, 1, 8, 2, 1, 1},};
        // 或者使用類似以下代碼
        // DefaultCategoryDataset categoryDataset = new
        // DefaultCategoryDataset();
        // categoryDataset.addValue(10, "rowKey", "colKey");
        CategoryDataset categoryDataset = DatasetUtilities.createCategoryDataset(rowKeys, colKeys, data);


        // 創建JFreeChart對象:ChartFactory.createLineChart
        JFreeChart jfreechart = ChartFactory.createLineChart("不同類別按小時計算拆線圖", // 標題
                "年分", // categoryAxisLabel (category軸,橫軸,X軸標籤)
                "數量", // valueAxisLabel(value軸,縱軸,Y軸的標籤)
                categoryDataset, // dataset
                PlotOrientation.VERTICAL, true, // legend
                false, // tooltips
                false); // URLs
        // 使用CategoryPlot設置各種參數。以下設置可以省略。
        CategoryPlot plot = (CategoryPlot)jfreechart.getPlot();
        //設置圖片標題的字體
        jfreechart.getTitle().setFont(new Font("新宋體", Font.BOLD, 15));
        //設置圖例項目字體
        jfreechart.getLegend().setItemFont(new Font("新宋體", Font.BOLD, 15));
        //得到繪圖區的域軸(橫軸),設置標籤的字體
        plot.getDomainAxis().setLabelFont(new Font("新宋體", Font.BOLD, 15));

        //設置橫軸標籤項字體
        plot.getDomainAxis().setTickLabelFont(new Font("新宋體", Font.BOLD, 15));
        //設置範圍軸(縱軸)字體
        plot.getRangeAxis().setLabelFont(new Font("新宋體", Font.BOLD, 15));

        // 背景色 透明度
        plot.setBackgroundAlpha(0.5f);
        // 前景色 透明度
        plot.setForegroundAlpha(0.5f);
        // 其他設置 參考 CategoryPlot類
        LineAndShapeRenderer renderer = (LineAndShapeRenderer)plot.getRenderer();
        renderer.setBaseShapesVisible(true); // series 點(即數據點)可見
        renderer.setBaseLinesVisible(true); // series 點(即數據點)間有連線可見
        renderer.setUseSeriesOffset(true); // 設置偏移量
        renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
        renderer.setBaseItemLabelsVisible(true);



        ByteArrayOutputStream out = null;
        try {
            out = new ByteArrayOutputStream();
            // 保存爲PNG
            ChartUtilities.writeChartAsPNG(out, jfreechart, 600, 400);
            out.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    // do nothing
                }
            }
        }

        return new ByteArrayDataSource(out.toByteArray(),"image/png");
    }

  

    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章