diff --git a/lib/Constants.php b/lib/Constants.php index 9ad6239f..ac3f58a9 100644 --- a/lib/Constants.php +++ b/lib/Constants.php @@ -38,8 +38,9 @@ const CAPTCHA_IMAGE_WIDTH = 230; const NO_REPLY_EMAIL_ADDRESS = 'admin@standardebooks.org'; const ADMIN_EMAIL_ADDRESS = 'admin@standardebooks.org'; const EDITOR_IN_CHIEF_EMAIL_ADDRESS = 'alex@standardebooks.org'; +const EDITOR_IN_CHIEF_NAME = 'Alex Cabal'; define('EMAIL_SMTP_USERNAME', get_cfg_var('se.secrets.postmark.username')); -const EMAIL_SMTP_HOST = 'smtp-broadcasts.postmarkapp.com'; +const EMAIL_SMTP_HOST = 'smtp.postmarkapp.com'; const EMAIL_POSTMARK_STREAM_BROADCAST = 'the-standard-ebooks-newsletter'; const REST = 0; diff --git a/lib/Email.php b/lib/Email.php index 84b41aa8..357e2ede 100644 --- a/lib/Email.php +++ b/lib/Email.php @@ -7,6 +7,7 @@ use function Safe\file_get_contents; class Email{ public $To = ''; + public $ToName = ''; public $From = ''; public $FromName = ''; public $ReplyTo = ''; @@ -43,7 +44,7 @@ class Email{ try{ $phpMailer->SetFrom($this->From, $this->FromName); $phpMailer->AddReplyTo($this->ReplyTo); - $phpMailer->AddAddress($this->To); + $phpMailer->AddAddress($this->To, $this->ToName); $phpMailer->Subject = $this->Subject; $phpMailer->CharSet = 'UTF-8'; if($this->TextBody !== null && $this->TextBody != ''){ diff --git a/lib/Patron.php b/lib/Patron.php index 6cd30bc5..f3f94311 100644 --- a/lib/Patron.php +++ b/lib/Patron.php @@ -33,7 +33,9 @@ class Patron extends PropertiesBase{ if($this->User !== null){ $em = new Email(); $em->To = $this->User->Email; + $em->ToName = $this->User->Name; $em->From = EDITOR_IN_CHIEF_EMAIL_ADDRESS; + $em->FromName = EDITOR_IN_CHIEF_NAME; $em->Subject = 'Thank you for supporting Standard Ebooks!'; $em->Body = Template::EmailPatronsCircleWelcome(['isAnonymous' => $this->IsAnonymous, 'isReturning' => $isReturning]); $em->TextBody = Template::EmailPatronsCircleWelcomeText(['isAnonymous' => $this->IsAnonymous, 'isReturning' => $isReturning]); diff --git a/lib/User.php b/lib/User.php index ff17ed70..b3524953 100644 --- a/lib/User.php +++ b/lib/User.php @@ -4,27 +4,12 @@ use Safe\DateTime; class User extends PropertiesBase{ public $UserId; - public $FirstName; - public $LastName; - protected $Name = null; + public $Name; public $Email; public $Created; public $Uuid; - // ******* - // GETTERS - // ******* - - protected function GetName(): string{ - if($this->Name === null){ - $this->Name = $this->FirstName . ' ' . $this->LastName; - } - - return $this->Name; - } - - // ******* // METHODS // ******* diff --git a/scripts/process-pending-payments b/scripts/process-pending-payments index d453b6cc..377acd4b 100755 --- a/scripts/process-pending-payments +++ b/scripts/process-pending-payments @@ -195,7 +195,9 @@ try{ $log->Write('Sending thank you email to non-patron donor.'); $em = new Email(); $em->To = $payment->User->Email; + $em->ToName = $payment->User->Name; $em->From = EDITOR_IN_CHIEF_EMAIL_ADDRESS; + $em->FromName = EDITOR_IN_CHIEF_NAME; $em->Subject = 'Thank you for supporting Standard Ebooks!'; $em->Body = Template::EmailDonationThankYou(); $em->TextBody = Template::EmailDonationThankYouText(); @@ -214,9 +216,7 @@ catch(Exception $ex){ $exceptionString = vds($ex); $log->Write('Error: Uncaught exception: ' . $exceptionString); - $em = new Email(); - $em->To = ADMIN_EMAIL_ADDRESS; - $em->From = NO_REPLY_EMAIL_ADDRESS; + $em = new Email(true); $em->Subject = 'Donation processing failed'; $em->Body = Template::EmailDonationProcessingFailed(['exception' => preg_replace('/^/m', "\t", $exceptionString)]); $em->TextBody = Template::EmailDonationProcessingFailedText(['exception' => preg_replace('/^/m', "\t", $exceptionString)]); diff --git a/scripts/update-patrons-circle b/scripts/update-patrons-circle index 676750d6..6ccafdd4 100755 --- a/scripts/update-patrons-circle +++ b/scripts/update-patrons-circle @@ -6,19 +6,74 @@ require_once('/standardebooks.org/web/lib/Core.php'); // who aren't in that list. // We give a 15 day grace period to Patrons Circle members because sometimes FA can be delayed in charging. -Db::Query(' - update Patrons - set Ended = utc_timestamp() - where UserId not in +$now = new DateTime(); +$lastYear = new DateTime('-1 year'); + +$expiredPatrons = Db::Query(' + select * from Patrons + where + Ended is null and + UserId not in ( select distinct UserId from Payments where UserId is not null and ( - (IsRecurring = 1 and Amount >= 10 and Created > utc_timestamp() - interval 45 day) + (IsRecurring = 1 and Amount >= 10 and Created > ? - interval 45 day) or - (IsRecurring = 0 and Amount >= 100 and Created > utc_timestamp() - interval 1 year) + (IsRecurring = 0 and Amount >= 100 and Created > ? - interval 1 year) ) ) -'); +', [$now, $now], 'Patron'); + +if(sizeof($expiredPatrons) > 0){ + $ebooksThisYear = 0; + + // We can't use the Library class to get ebooks because this script is typically run via cron or CLI, + // which doesn't have access PHP-FMP's APCu cache. + foreach(explode("\n", trim(shell_exec('find ' . EBOOKS_DIST_PATH . ' -name "content.opf"') ?? '')) as $filename){ + $metadata = file_get_contents($filename); + + // Don't create a new Ebook object because that's very slow. Just do a regex match for speed. + preg_match_all('/(.+?)<\/dc:date>/iu', $metadata, $matches); + + if(sizeof($matches) > 0){ + $created = new DateTime($matches[1][0]); + if($created >= $lastYear){ + $ebooksThisYear++; + } + } + } + + foreach($expiredPatrons as $patron){ + Db::Query('update Patrons set Ended = ? where UserId = ?', [$now, $patron->UserId]); + + // Email the patron to notify them their term has ended + // Is the patron a recurring subscriber? + $lastPayment = Db::Query('select * from Payments where UserId = ? order by Created desc limit 1;', [$patron->UserId], 'Payment'); + + if(sizeof($lastPayment) > 0 && $patron->User->Email !== null){ + $em = new Email(); + $em->From = EDITOR_IN_CHIEF_EMAIL_ADDRESS; + $em->FromName = EDITOR_IN_CHIEF_NAME; + $em->To = $patron->User->Email; + $em->ToName = $patron->Name; + $em->Subject = 'Will you continue supporting beautiful digital literature?'; + + if($lastPayment[0]->IsRecurring){ + // Email recurring donors who have lapsed + $em->Body = Template::EmailPatronsCircleRecurringCompleted(); + $em->TextBody = Template::EmailPatronsCircleRecurringCompletedText(); + } + else{ + // Email one time donors who have expired after one year + $em->Body = Template::EmailPatronsCircleCompleted(['ebooksThisYear' => $ebooksThisYear]); + $em->TextBody = Template::EmailPatronsCircleCompletedText(['ebooksThisYear' => $ebooksThisYear]); + } + + $em->Send(); + } + } +} + ?> diff --git a/templates/EmailFooter.php b/templates/EmailFooter.php index 87790b68..23fc5188 100644 --- a/templates/EmailFooter.php +++ b/templates/EmailFooter.php @@ -1,9 +1,9 @@