001/* 002 * Copyright 2006-2010 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.springframework.batch.item.mail.javamail; 017 018import org.springframework.batch.item.ItemWriter; 019import org.springframework.batch.item.mail.DefaultMailErrorHandler; 020import org.springframework.batch.item.mail.MailErrorHandler; 021import org.springframework.beans.factory.InitializingBean; 022import org.springframework.mail.MailException; 023import org.springframework.mail.MailSendException; 024import org.springframework.mail.javamail.JavaMailSender; 025import org.springframework.mail.javamail.MimeMailMessage; 026import org.springframework.util.Assert; 027 028import javax.mail.internet.MimeMessage; 029import java.util.List; 030import java.util.Map; 031import java.util.Map.Entry; 032 033/** 034 * <p> 035 * A simple {@link ItemWriter} that can send mail messages. If it fails there is 036 * no guarantee about which of the messages were sent, but the ones that failed 037 * can be picked up in the error handler. Because the mail protocol is not 038 * transactional, failures should be dealt with here if possible rather than 039 * allowing them to be rethrown (which is the default). 040 * </p> 041 * 042 * <p> 043 * Delegates the actual sending of messages to a {@link JavaMailSender}, using the 044 * batch method {@link JavaMailSender#send(MimeMessage[])}, which normally uses 045 * a single server connection for the whole batch (depending on the 046 * implementation). The efficiency of for large volumes of messages (repeated 047 * calls to the item writer) might be improved by the use of a special 048 * {@link JavaMailSender} that caches connections to the server in between 049 * calls. 050 * </p> 051 * 052 * <p> 053 * Stateless, so automatically restartable. 054 * </p> 055 * 056 * @author Dave Syer 057 * 058 * @since 2.1 059 * 060 */ 061public class MimeMessageItemWriter implements ItemWriter<MimeMessage> { 062 063 private JavaMailSender mailSender; 064 065 private MailErrorHandler mailErrorHandler = new DefaultMailErrorHandler(); 066 067 /** 068 * A {@link JavaMailSender} to be used to send messages in {@link #write(List)}. 069 * 070 * @param mailSender service for doing the work of sending a MIME message 071 */ 072 public void setJavaMailSender(JavaMailSender mailSender) { 073 this.mailSender = mailSender; 074 } 075 076 /** 077 * The handler for failed messages. Defaults to a 078 * {@link DefaultMailErrorHandler}. 079 * 080 * @param mailErrorHandler the mail error handler to set 081 */ 082 public void setMailErrorHandler(MailErrorHandler mailErrorHandler) { 083 this.mailErrorHandler = mailErrorHandler; 084 } 085 086 /** 087 * Check mandatory properties (mailSender). 088 * 089 * @throws IllegalStateException if the mandatory properties are not set 090 * 091 * @see InitializingBean#afterPropertiesSet() 092 */ 093 public void afterPropertiesSet() throws IllegalStateException { 094 Assert.state(mailSender != null, "A MailSender must be provided."); 095 } 096 097 /** 098 * @param items the items to send 099 * @see ItemWriter#write(List) 100 */ 101 @Override 102 public void write(List<? extends MimeMessage> items) throws MailException { 103 try { 104 mailSender.send(items.toArray(new MimeMessage[items.size()])); 105 } 106 catch (MailSendException e) { 107 Map<Object, Exception> failedMessages = e.getFailedMessages(); 108 for (Entry<Object, Exception> entry : failedMessages.entrySet()) { 109 mailErrorHandler.handle(new MimeMailMessage((MimeMessage)entry.getKey()), entry.getValue()); 110 } 111 } 112 } 113 114}