/*********************************************************************************
* The contents of this file are subject to the Common Public Attribution
* License Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.openemm.org/cpal1.html. The License is based on the Mozilla
* Public License Version 1.1 but Sections 14 and 15 have been added to cover
* use of software over a computer network and provide for limited attribution
* for the Original Developer. In addition, Exhibit A has been modified to be
* consistent with Exhibit B.
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is OpenEMM.
* The Original Developer is the Initial Developer.
* The Initial Developer of the Original Code is AGNITAS AG. All portions of
* the code written by AGNITAS AG are Copyright (c) 2007 AGNITAS AG. All Rights
* Reserved.
*
* Contributor(s): AGNITAS AG.
********************************************************************************/
package org.agnitas.backend;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Hashtable;
import org.agnitas.util.Log;
/** General parent class for all types of creating mail output
*/
abstract public class MailWriter {
/** Reference to configuration */
protected Data data;
/** Collection of all available blocks */
protected BlockCollection allBlocks;
/** Interface to write billing information */
protected BillingCounter billingCounter;
/** To create boundaries */
protected String fileSequence;
/** Prefix for message IDs */
protected String messageIDStart;
/** Boundary to separate text from html part */
protected String innerBoundary;
/** Boundary to separate content from images */
protected String outerBoundary;
/** Boundary to separate attachmantes from rest of mail */
protected String attachBoundary;
/** Used in subclass to create pathnames */
protected String dirSeparator;
/** Start time of writing mail */
public Date startExecutionTime;
/** End time of writing mail */
public Date endExecutionTime;
/** Start time of writing current block */
public Date startBlockTime;
/** End time of writing current block */
public Date endBlockTime;
/** number of mails written */
public long mailCount;
/** max. number of receiver of a single block */
public long blockSize;
/** number of blocks written */
public long blockCount;
/** number of mails written in current block */
protected long inBlockCount;
/** pattern for creating filenames for writing blocks */
protected String filenamePattern;
/** mailtype for the current receiver */
protected int mailType;
/** message ID for the current receiver */
protected String messageID;
/** internal used, if set we need to increase number of created mails */
private boolean pending;
/** to create unique filenamnes */
private static long uniqts = 0;
/** to create unique filenamnes */
private static long uniqnr = 0;
/** Create a unique number based on given timestamp
* @param ts current timestamp
* @return unique number as string
*/
private synchronized String getUniqueNr (long ts, int minLength) {
if (uniqts == ts)
++uniqnr;
else {
uniqts = ts;
uniqnr = 1;
}
return StringOps.format_number (Long.toString (uniqnr), minLength);
}
/** Create the prefix for messageIDs
*/
protected void createMessageIDPrefix () {
Calendar today;
today = Calendar.getInstance ();
messageIDStart = Integer.toString (today.get (Calendar.YEAR)) +
StringOps.format_number (Integer.toString (today.get(Calendar.MONTH)+1), 2) +
StringOps.format_number (Integer.toString (today.get(Calendar.DAY_OF_MONTH)), 2) +
StringOps.format_number (Integer.toString (today.get(Calendar.HOUR_OF_DAY)),2) +
StringOps.format_number (Integer.toString (today.get(Calendar.MINUTE)),2) +
StringOps.format_number (Integer.toString (today.get(Calendar.SECOND)),2);
}
/** Constructor
* @param data reference to configuration
* @param allBlocks reference to all content blocks
*/
public MailWriter (Data data, BlockCollection allBlocks) throws Exception {
this.data = data;
this.allBlocks = allBlocks;
// setup billing interface
if (data.isAdminMailing () || data.isTestMailing () || data.isWorldMailing ()) {
billingCounter = new BillingCounter(data);
} else
billingCounter = null;
// Create pre-string for the two mail files
fileSequence = StringOps.format_number (Long.toHexString (data.mailing_id).toUpperCase (), 6);
messageIDStart = null;
// create boundaries
innerBoundary = "-==" + data.boundary + "INNERB164240059B29" + fileSequence + "==";
outerBoundary = "-==" + data.boundary + "OUTER164240059B29" + fileSequence + "==";
attachBoundary = "-==" + data.boundary + "ATTACH164240059B29" + fileSequence + "==";
dirSeparator = System.getProperty ("file.separator");
startExecutionTime = new Date ();
endExecutionTime = null;
startBlockTime = null;
endBlockTime = null;
// set counters
mailCount = 0;
blockSize = 0;
blockCount = 0;
inBlockCount = 0;
filenamePattern = null;
messageID = null;
pending = false;
}
/** Cleanup
*/
protected void done () throws Exception {
endBlock ();
if (billingCounter != null) {
billingCounter.write_db (blockSize, blockCount);
billingCounter.output ();
billingCounter = null;
}
endExecutionTime = new Date ();
}
/** Setup everything to start a new block
*/
protected void startBlock () throws Exception {
long timestamp, now;
++blockCount;
inBlockCount = 0;
timestamp = data.sendSeconds;
if (data.step > 0)
if (data.isCampaignMailing ())
timestamp += data.step * 60;
else if (blockCount > data.startBlockForStep)
timestamp += (data.step * 60) * ((blockCount - data.startBlockForStep) / data.blocksPerStep);
now = System.currentTimeMillis () / 1000;
if (timestamp < now)
timestamp = now;
data.currentSendDate = new Date (timestamp * 1000);
String tsstr;
SimpleDateFormat tmp;
tmp = new SimpleDateFormat ("'D'yyyyMMddHHmmss");
tsstr = tmp.format (data.currentSendDate).toString ();
String unique;
if (data.isCampaignMailing ())
unique = getUniqueNr (timestamp, 1) + "C" + (data.status_field != null ? data.status_field : "") +
StringOps.format_number (Long.toString(data.campaignTransactionID > 0 ? data.campaignTransactionID : data.campaignCustomerID), 8);
else if (data.isAdminMailing () || data.isTestMailing () || data.isPreviewMailing ())
unique = getUniqueNr (timestamp, 5);
else
unique = StringOps.format_number (Long.toString (blockCount), 4);
filenamePattern = "AgnMail" + data.getFilenameDetail () +
"=" + tsstr +
"=" + data.getFilenameCompanyID () +
"=" + data.getFilenameMailingID () +
"=" + unique +
"=liaMngA";
data.logging (Log.INFO, "writer", "Start block " + blockCount + " using blocksize " + blockSize);
if (billingCounter != null)
billingCounter.debug_out ();
startBlockTime = new Date ();
}
/** Mark everything for ending the block
*/
protected void endBlock () throws Exception {
endBlockTime = new Date ();
data.logging (Log.INFO, "writer", "End block " + blockCount);
}
/** Check if we need to create a new block
* @param force force start of a new block
*/
protected void checkBlock (boolean force) throws Exception {
if (blockCount == 0) {
startBlock ();
}
if ((blockSize > 0) && (force || (inBlockCount >= blockSize))) {
endBlock ();
startBlock ();
}
}
/** When a mail is written, increase counter
*/
protected void writeMailDone () {
if (pending) {
pending = false;
++mailCount;
++inBlockCount;
}
}
/** Write information for a single receiver
* @param cinfo Information about the customer
* @param mcount if more than one mail is written for this receiver
* @param mailtype the mailtype for this receiver
* @param icustomer_id the customer ID
* @param tag_names the available tags
* @param urlMaker to create the URLs
*/
protected void writeMail (Custinfo cinfo,
int mcount, int mailtype, long icustomer_id,
String mediatypes, Hashtable tag_names,
URLMaker urlMaker) throws Exception {
EMMTag mid, uid;
writeMailDone ();
mailType = mailtype;
if (messageIDStart == null) {
createMessageIDPrefix ();
}
urlMaker.setPrefix (messageIDStart + "-" + (mcount > 0 ? Integer.toString (mcount) : "") + mailtype);
urlMaker.setURLID (0);
messageID = urlMaker.makeUID () + "@" + data.domain;
urlMaker.setPrefix (null);
mid = (EMMTag) tag_names.get (EMMTag.internalTag (EMMTag.TI_MESSAGEID));
if (mid != null) {
mid.mTagValue = messageID;
}
uid = (EMMTag) tag_names.get (EMMTag.internalTag (EMMTag.TI_UID));
if (uid != null) {
uid.mTagValue = urlMaker.makeUID ();
}
checkBlock (false);
pending = true;
}
}