Source file: src/mailing.cpp
/* Copyright (C) 2004-2011 Daniel Verite
This file is part of Manitou-Mail (see http://www.manitou-mail.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "db.h"
#include "sqlstream.h"
#include "date.h"
#include "main.h"
#include "mailing.h"
#include "text_merger.h"
#include <QList>
#include <QProgressBar>
#include <QBuffer>
#include <QByteArray>
bool
mailings::load()
{
db_cnx db;
try {
sql_stream s("SELECT md.mailing_id,title,to_char(creation_date,'YYYYMMDDHH24MISS'),status,nb_sent,nb_total FROM mailing_definition md JOIN mailing_run USING(mailing_id) ORDER BY 1 DESC", db);
while (!s.eof()) {
mailing_db m;
m.init_from_db(s);
append(m);
}
}
catch(db_excpt& p) {
DBEXCPT(p);
return false;
}
return true;
}
void
mailing_db::init_from_db(sql_stream& s)
{
QString sdate;
s >> m_id >> m_title >> sdate >> m_status >> m_nb_sent >> m_nb_total;
m_creation_date = date(sdate);
}
bool
mailing_db::create(const mailing_options& options)
{
db_cnx db;
try {
db.begin_transaction();
sql_stream s("INSERT INTO mailing_definition(title,sender_email,header_template, text_template, html_template, csv_columns) VALUES(:ti,:se,:hh,:tt,:ht,:cs) RETURNING mailing_id, to_char(creation_date,'YYYYMMDDHH24MISS')", db);
QString str_date;
s << options.title << options.sender_email << options.header;
s << options.text_part << options.html_part;
if (options.field_names.size() > 0) {
// CSV stuff
QStringList csv_columns = options.field_names;
csv_columns.removeFirst(); // remove the email column, we store in a dedicated field
QString csv_header = csv_columns.join(QString("%1").arg(options.csv_separator));
s << csv_header;
}
else
s << sql_null();
s >> m_id >> str_date;
m_title = options.title;
m_creation_date = date(str_date);
sql_stream s1("INSERT INTO mailing_run(mailing_id,status,throughput,nb_total,nb_sent) VALUES(:p1,:st,1.0,:tot,0)", db);
s1 << m_id << m_status << options.mail_addresses.size();
db.commit_transaction();
return true;
}
catch(db_excpt& p) {
db.rollback_transaction();
DBEXCPT(p);
return false;
}
return true;
}
bool
mailing_db::load_data(mailing_options* opt)
{
db_cnx db;
try {
sql_stream s("SELECT recipient_email, csv_data FROM mailing_data WHERE mailing_id=:id ORDER BY mailing_data_id", db);
s << m_id;
QString email;
QString csv_line;
text_merger tm;
tm.init(opt->field_names, ',');
while (!s.eos()) {
s >> email >> csv_line;
opt->mail_addresses.append(email);
if (!csv_line.isEmpty()) {
QByteArray arr = csv_line.toUtf8();
QBuffer buffer(&arr);
buffer.open(QBuffer::ReadWrite);
QStringList csv_values = tm.collect_data(&buffer);
opt->csv_data.append(csv_values);
}
}
}
catch(db_excpt& p) {
DBEXCPT(p);
return false;
}
return true;
}
bool
mailing_db::load_definition(mailing_options* options)
{
db_cnx db;
try {
m_status=0;
sql_stream s("SELECT title,sender_email,header_template, text_template, html_template, csv_columns FROM mailing_definition WHERE mailing_id=:id", db);
QString csv_columns;
s << m_id;
s >> options->title >> options->sender_email >> options->header;
s >> options->text_part >> options->html_part >> csv_columns;
if (!csv_columns.isEmpty()) {
text_merger tm;
/* we don't set the separator since text_merger has by default the same separator
than the database contents (comma) */
options->field_names = tm.column_names(csv_columns);
options->field_names.insert(0, "email");
}
else
options->field_names.clear();
return true;
}
catch(db_excpt& p) {
DBEXCPT(p);
return false;
}
return true;
}
/* Store all the data for a mailing in a single operation.
The caller is assumed to have opened a transaction.
TODO: use COPY for improved speed
*/
bool
mailing_db::store_data(const QStringList& recipients, const QList<QStringList>& data_lines,
QProgressBar* bar)
{
db_cnx db;
try {
int i=0;
int step=recipients.size()/100;
if (bar)
bar->setRange(0, recipients.size());
sql_stream s("INSERT INTO mailing_data(mailing_id, recipient_email, csv_data) VALUES(:id,:s, :data)", db);
QList<QStringList>::const_iterator itd = data_lines.constBegin();
for (QStringList::const_iterator iter = recipients.constBegin();
iter!=recipients.constEnd();
++iter)
{
if (bar && (step==0 || (i++%step)==0)) {
bar->setValue(i);
bar->update();
}
s << m_id << *iter;
if (itd != data_lines.constEnd()) {
QString csv_line = text_merger::csv_join(*itd, ',');
s << csv_line;
++itd;
}
else
s << sql_null();
}
}
catch(db_excpt& p) {
DBEXCPT(p);
return false;
}
return true;
}
bool
mailing_db::stop()
{
db_cnx db;
try {
sql_stream s1("UPDATE mailing_run SET status=:s WHERE mailing_id=:id", db);
s1 << status_stopped << m_id;
m_status = status_stopped;
}
catch(db_excpt& p) {
DBEXCPT(p);
return false;
}
return true;
}
bool
mailing_db::instantiate_job()
{
db_cnx db;
try {
db.begin_transaction();
sql_stream s1("UPDATE mailing_run SET status=:s WHERE mailing_id=:id", db);
s1 << status_running << m_id;
sql_stream s("INSERT INTO jobs_queue(job_type, job_args) SELECT :t,:a WHERE NOT EXISTS (SELECT 1 FROM jobs_queue WHERE job_type=:t1 AND job_args=:a1)", db);
s << "mailing" << QString("%1").arg(m_id);
s << "mailing" << QString("%1").arg(m_id);
db.commit_transaction();
m_status=status_running; // 1
}
catch(db_excpt& p) {
db.rollback_transaction();
DBEXCPT(p);
return false;
}
return true;
}
QString
mailing_db::status_text() const
{
static const char* txt[] = {
QT_TR_NOOP("Not started"),
QT_TR_NOOP("Running"),
QT_TR_NOOP("Stopped"),
QT_TR_NOOP("Done")
};
if (m_status>=0 && m_status<(int)(sizeof(txt)/sizeof(txt[0]))) {
return QObject::tr(txt[m_status]);
}
else
return QString::null;
}
bool
mailing_db::purge()
{
db_cnx db;
try {
db.begin_transaction();
sql_stream s1("UPDATE mailing_run SET status=:s WHERE mailing_id=:id", db);
s1 << status_stopped << m_id;
sql_stream s2("DELETE FROM mailing_data WHERE mailing_id=:id", db);
s2 << m_id;
sql_stream s3("DELETE FROM mailing_run WHERE mailing_id=:id", db);
s3 << m_id;
sql_stream s4("DELETE FROM mailing_definition WHERE mailing_id=:id", db);
s4 << m_id;
db.commit_transaction();
m_status = status_stopped;
}
catch(db_excpt& p) {
db.rollback_transaction();
DBEXCPT(p);
return false;
}
return true;
}
/* Filter out characters that would be invalid for the
mailing_db.header_template column */
//static
QString
mailing_db::filter_header_line(QString line)
{
// maybe filter some other characters?
line.replace("\n", " ");
return line;
}
HTML source code generated by GNU Source-Highlight plus some custom post-processing
List of all available source files