tasks/send-autoresponder-emails
#!/usr/bin/env perl
# ===================================================================
# File: tasks/send-autoresponder-emails
# Project: ShinyCMS
# Purpose: Check for queued autoresponder emails and send them
#
# Author: Denny de la Haye <2019@denny.me>
# Copyright (c) 2009-2019 Denny de la Haye
#
# ShinyCMS is free software; you can redistribute it and/or modify it
# under the terms of either the GPL 2.0 or the Artistic License 2.0
# ===================================================================
use strict;
use warnings;
# Local modules
use FindBin qw( $Bin );
use lib "$Bin/../lib";
use ShinyCMS;
use ShinyCMS::Schema;
# Exit if already running
use File::Pid;
my $pidfile = File::Pid->new({
file => '/tmp/shinycms-send-autoresponder-emails.'. ShinyCMS->config->{ domain } .'.pid',
});
if ( my $num = $pidfile->running ) {
die "Already running: $num\n";
}
$pidfile->write;
# CPAN modules
use Template;
use Email::MIME;
use Email::Sender::Simple qw( try_to_sendmail );
my $debug = 0; # enable/disable debugging output
# Get a database connection
my $schema = ShinyCMS::Schema->connect(
ShinyCMS->config->{ 'Model::DB' }->{ connect_info }
);
# Get the current date and time
my $now = DateTime->now;
my $cur = $now->date .' '. $now->time;
# Find emails that are marked or scheduled for sending
my @q_emails = $schema->resultset( 'QueuedEmail' )->search([
{
status => 'Test',
send => { '<' => $cur },
},
{
status => 'Not Sent',
send => { '<' => $cur },
},
]);
# Loop through the emails
foreach my $q_email ( @q_emails ) {
my $ar_email = $q_email->email;
print 'Processing email: ', $ar_email->subject, "\n" if $debug;
# Build up the email body data
my $data = {};
$data->{ email } = $ar_email;
$data->{ site_name } = ShinyCMS->config->{ site_name };
$data->{ site_url } = 'http://'. ShinyCMS->config->{ domain };
# Get email elements
my @elements = $ar_email->autoresponder_email_elements->all;
$data->{ email_elements } = \@elements;
# Build up 'elements' structure for use by templates
foreach my $element ( @elements ) {
$data->{ elements }->{ $element->name } = $element->content;
}
# Create the template object
my $tt = Template->new({
INCLUDE_PATH => ShinyCMS->path_to( 'root/newsletters/newsletter-templates' ),
});
# Build up the email
my @parts = (
Email::MIME->create(
attributes => {
content_type => "text/plain",
charset => "UTF-8",
},
),
Email::MIME->create(
attributes => {
content_type => "text/html",
charset => "UTF-8",
},
),
);
my $email_from = '"' . ShinyCMS->config->{ site_name }
. '" <' . ShinyCMS->config->{ site_email } . '>';
my $email = Email::MIME->create(
header => [
From => $email_from,
Subject => $ar_email->subject,
'Content-Type' => 'multipart/alternative; charset="UTF-8"',
],
);
# Send email to recipient
my $recipient = $q_email->recipient;
print 'Sending email to ', $recipient->name, "\n" if $debug;
# Set the recipient in the email header
$email->header_set(
To => $recipient->name .' <'. $recipient->email .'>'
);
# Add the recipient name+email to the template data
$data->{ recipient } = $recipient;
# Build the email
my $html_body = '';
$tt->process( $ar_email->template->filename, $data, \$html_body )
|| die $tt->error, "\n";
# Make image src URLs absolute and URL-encoded
$html_body =~ s/src="([^"]+)"/fix_URLs($1)/egis;
# Remove DOS line-endings, because they confuse Outlook.com (?!)
$html_body =~ s/\r\n/\n/;
# Set the body of the email
$parts[0]->body_set( $ar_email->plaintext );
$parts[1]->body_set( $html_body );
$email->parts_set( [ @parts ] );
# Send the email
my $status = try_to_sendmail( $email );
if ( $status ) {
# Update the status appropriately
$q_email->update({ status => 'Sent' });
# Check to see if this was the last email in the stack, and if so,
# check if we need to subscribe the recipient to a mailing list now
my $last_email = $ar_email->autoresponder->autoresponder_emails->search(
{},
{
order_by => { -desc => 'delay' }
}
)->first;
if ( $last_email->id == $ar_email->id ) {
$recipient->subscriptions->create({
list => $ar_email->autoresponder->mailing_list->id;
});
}
}
else {
# Sending failed
print STDERR "Failed to send email to ", $recipient->email, "\n";
print STDERR $email->as_string, "\n" if $debug;
}
}
# Remove the PID file
$pidfile->remove;
sub fix_URLs {
my $url = shift @_;
# URL encoding for spaces
$url =~ s/ /%20/g;
# Absolute URLs
my $site_url = 'http://'. ShinyCMS->config->{ domain };
unless ( $url =~ m{^https?://} ) {
$url = $site_url . $url;
}
return 'src="'. $url .'"';
}