From 7f69ed596d7e89b0813502ec27f2e36cd6a595b8 Mon Sep 17 00:00:00 2001 From: Charles Drew <cdrew@directvetmarketing.com> Date: Fri, 20 Jun 2014 15:35:13 -0400 Subject: [PATCH] Initial Committ --- app/LICENSE | 21 ++ app/README.md | 4 + .../Block/Adminhtml/Customer/Email.php | 13 + .../Block/Adminhtml/Customer/Email/Grid.php | 66 ++++ .../Block/Adminhtml/Customer/Tab/Mailgun.php | 37 +++ .../MailGun/Block/Adminhtml/Emailtracking.php | 75 +++++ .../Block/Adminhtml/Event/Container.php | 13 + .../MailGun/Block/Adminhtml/Event/Grid.php | 50 +++ .../Adminhtml/Event/Renderer/Timestamp.php | 10 + .../Block/Adminhtml/Event/Renderer/Type.php | 9 + .../Block/Adminhtml/Global/Container.php | 13 + .../MailGun/Block/Adminhtml/Global/Grid.php | 66 ++++ .../FreeLunchLabs/MailGun/Helper/Data.php | 5 + .../FreeLunchLabs/MailGun/Model/Email.php | 48 +++ .../MailGun/Model/Email/Template.php | 133 ++++++++ .../FreeLunchLabs/MailGun/Model/Event.php | 36 +++ .../Model/Exceptions/InvalidParameter.php | 5 + .../Model/Exceptions/InvalidParameterType.php | 5 + .../MissingRequiredMIMEParameters.php | 5 + .../Model/Exceptions/TooManyParameters.php | 5 + .../FreeLunchLabs/MailGun/Model/Mailgun.php | 120 +++++++ .../MailGun/Model/Messagebuilder.php | 296 ++++++++++++++++++ .../MailGun/Model/Resource/Email.php | 26 ++ .../Model/Resource/Email/Collection.php | 38 +++ .../MailGun/Model/Resource/Event.php | 10 + .../Model/Resource/Event/Collection.php | 11 + .../Adminhtml/EmailtrackingController.php | 96 ++++++ .../FreeLunchLabs/MailGun/etc/config.xml | 151 +++++++++ .../FreeLunchLabs/MailGun/etc/system.xml | 111 +++++++ .../mailgun_setup/mysql4-install-1.0.0.php | 33 ++ .../default/default/layout/mailgun.xml | 21 ++ .../template/mailgun/customer/tab/tab.phtml | 1 + .../template/mailgun/emaildetail.phtml | 90 ++++++ .../template/mailgun/globalemailgrid.phtml | 15 + app/etc/modules/FreeLunchLabs_MailGun.xml | 9 + 35 files changed, 1647 insertions(+) create mode 100644 app/LICENSE create mode 100644 app/README.md create mode 100644 app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Customer/Email.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Customer/Email/Grid.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Customer/Tab/Mailgun.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Emailtracking.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Container.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Grid.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Renderer/Timestamp.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Renderer/Type.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Global/Container.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Global/Grid.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Helper/Data.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Model/Email.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Model/Email/Template.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Model/Event.php create mode 100755 app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/InvalidParameter.php create mode 100755 app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/InvalidParameterType.php create mode 100755 app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/MissingRequiredMIMEParameters.php create mode 100755 app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/TooManyParameters.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Model/Mailgun.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Model/Messagebuilder.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Model/Resource/Email.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Model/Resource/Email/Collection.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Model/Resource/Event.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/Model/Resource/Event/Collection.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/controllers/Adminhtml/EmailtrackingController.php create mode 100644 app/code/community/FreeLunchLabs/MailGun/etc/config.xml create mode 100644 app/code/community/FreeLunchLabs/MailGun/etc/system.xml create mode 100644 app/code/community/FreeLunchLabs/MailGun/sql/mailgun_setup/mysql4-install-1.0.0.php create mode 100644 app/design/adminhtml/default/default/layout/mailgun.xml create mode 100644 app/design/adminhtml/default/default/template/mailgun/customer/tab/tab.phtml create mode 100644 app/design/adminhtml/default/default/template/mailgun/emaildetail.phtml create mode 100644 app/design/adminhtml/default/default/template/mailgun/globalemailgrid.phtml create mode 100644 app/etc/modules/FreeLunchLabs_MailGun.xml diff --git a/app/LICENSE b/app/LICENSE new file mode 100644 index 0000000..0ada34d --- /dev/null +++ b/app/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 chuckdrew + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/app/README.md b/app/README.md new file mode 100644 index 0000000..b927393 --- /dev/null +++ b/app/README.md @@ -0,0 +1,4 @@ +mailgin_magento +=============== + +Mailgun extension for Magento diff --git a/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Customer/Email.php b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Customer/Email.php new file mode 100644 index 0000000..95cd488 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Customer/Email.php @@ -0,0 +1,13 @@ +<?php + +class FreeLunchLabs_MailGun_Block_Adminhtml_Customer_Email extends Mage_Adminhtml_Block_Widget_Grid_Container { + + protected function _construct() { + parent::_construct(); + + $this->_blockGroup = 'freelunchlabs_mailgun'; + $this->_controller = 'adminhtml_customer_email'; + $this->_headerText = false; + + } +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Customer/Email/Grid.php b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Customer/Email/Grid.php new file mode 100644 index 0000000..3ba02dd --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Customer/Email/Grid.php @@ -0,0 +1,66 @@ +<?php + +class FreeLunchLabs_MailGun_Block_Adminhtml_Customer_Email_Grid extends Mage_Adminhtml_Block_Widget_Grid { + + public function __construct() { + parent::__construct(); + $this->setId('mailgun_email_grid'); + $this->setDefaultSort('id'); + $this->setDefaultDir('ASC'); + $this->setUseAjax(true); + $this->setFilterVisibility(true); + } + + protected function _prepareCollection() { + $collection = Mage::getResourceModel('freelunchlabs_mailgun/email_collection')->getGridCollection(); + + //Filter on Customer + $collection->addFieldToFilter('customer_id', Mage::registry('current_customer')->getId()); + + $this->setCollection($collection); + return parent::_prepareCollection(); + } + + protected function _prepareColumns() { + + $this->addColumn('subject', array( + 'header' => 'Subject', + 'type' => 'text', + 'index' => 'subject' + )); + + $this->addColumn('mailgun_id', array( + 'header' => 'Mailgun ID', + 'type' => 'text', + 'index' => 'mailgun_id' + )); + + $this->addColumn('current_status', array( + 'header' => 'Latest Status', + 'index' => 'current_status', + 'renderer' => 'FreeLunchLabs_MailGun_Block_Adminhtml_Event_Renderer_Type' + )); + + $this->addColumn('date_sent', array( + 'header' => 'Date Sent', + 'type' => 'datetime', + 'index' => 'date_sent' + )); + + return parent::_prepareColumns(); + } + + public function getRowUrl($row) { + return $this->getUrl('*/emailTracking/emailDetail', array( + 'id' => $row->getId() + )); + } + + public function getGridUrl() { + return $this->getUrl('*/emailtracking/emailGrid', array( + '_current' => true, + 'id' => Mage::registry('current_customer')->getId() + )); + } + +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Customer/Tab/Mailgun.php b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Customer/Tab/Mailgun.php new file mode 100644 index 0000000..dc92238 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Customer/Tab/Mailgun.php @@ -0,0 +1,37 @@ +<?php + +class FreeLunchLabs_MailGun_Block_Adminhtml_Customer_Tab_Mailgun extends Mage_Adminhtml_Block_Template implements Mage_Adminhtml_Block_Widget_Tab_Interface { + + public function _construct() { + parent::_construct(); + + $this->setTemplate('mailgun/customer/tab/tab.phtml'); + } + + public function getTabLabel() { + return $this->__('Email Tracking'); + } + + public function getTabTitle() { + return $this->__('View emails sent to this customer and the email history'); + } + + public function canShowTab() { + return Mage::getStoreConfig('mailgun/events/store'); + } + + public function isHidden() { + return false; + } + + public function getAfter() { + return 'tags'; + } + + public function getGrid() { + $gridBlock = $this->getLayout()->createBlock('freelunchlabs_mailgun/adminhtml_customer_email'); + + return $gridBlock->getGridHtml(); + } + +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Emailtracking.php b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Emailtracking.php new file mode 100644 index 0000000..f4d2d8e --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Emailtracking.php @@ -0,0 +1,75 @@ +<?php + +class FreeLunchLabs_MailGun_Block_Adminhtml_Emailtracking extends Mage_Adminhtml_Block_Template { + + function getFetchActivityUrl() { + return $this->getUrl('*/*/getEmailEvents'); + } + + public function getEmailDetail() { + $email = Mage::registry('current_email'); + + if ($email->getCustomerId()) { + $customer = Mage::getModel('customer/customer')->load($email->getCustomerId()); + $email->setCustomer($customer); + } + + return $email; + } + + public function getBackButtonHtml() { + return $this->getLayout()->createBlock('adminhtml/widget')->getButtonHtml('Back', 'history.back()', 'back'); + } + + public function getViewEmailBodyButtonHtml($emailId) { + $url = $this->getUrl('*/*/emailView', array( + 'id' => $emailId + )); + + $onClick = "window.open('{$url}','name','width=700,height=800')"; + + return $this->getLayout()->createBlock('adminhtml/widget')->getButtonHtml('View Email Body', $onClick); + } + + public function getEditCustomerUrl($customerId) { + return $url = $this->getUrl('*/customer/edit', array( + 'id' => $customerId + )); + } + + public function getCustomerGroupName($customerGroupId) { + return Mage::getModel('customer/group')->load($customerGroupId)->getCustomerGroupCode(); + } + + public function formatCustomerCreateDate($createdTimestamp) { + return Mage::helper('core')->formatDate($createdTimestamp, Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM, true); + } + + public function getFetch24HoursOfEmailActivityButton() { + $onClick = "setLocation('{$this->getFetchActivityUrl()}')"; + + return $this->getLayout()->createBlock('adminhtml/widget')->getButtonHtml('Fetch Past 24 Hours of Email Activity', $onClick); + } + + public function getDeleteEmailTrackingLogsDaysButton() { + $days = Mage::getStoreConfig('mailgun/events/days'); + + if ($days) { + $url = $this->getUrl('*/*/deleteEmailTrackingLogsDays'); + $onClick = "confirmSetLocation('Are you sure?', '{$url}')"; + + return $this->getLayout()->createBlock('adminhtml/widget')->getButtonHtml("Delete Email Records Older Than {$days} Days", $onClick, 'delete'); + } else { + return ""; + } + } + + public function getDeleteAllEmailTrackingLogsButton() { + $url = $this->getUrl('*/*/deleteEmailTrackingLogs'); + $onClick = "confirmSetLocation('Are you sure?', '{$url}')"; + + return $this->getLayout()->createBlock('adminhtml/widget')->getButtonHtml('Delete All Email Records', $onClick, 'delete'); + } + +} + diff --git a/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Container.php b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Container.php new file mode 100644 index 0000000..8bbd5ba --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Container.php @@ -0,0 +1,13 @@ +<?php + +class FreeLunchLabs_MailGun_Block_Adminhtml_Event_Container extends Mage_Adminhtml_Block_Widget_Grid_Container { + + protected function _construct() { + parent::_construct(); + + $this->_blockGroup = 'freelunchlabs_mailgun'; + $this->_controller = 'adminhtml_event'; + $this->_headerText = false; + + } +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Grid.php b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Grid.php new file mode 100644 index 0000000..7925c06 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Grid.php @@ -0,0 +1,50 @@ +<?php + +class FreeLunchLabs_MailGun_Block_Adminhtml_Event_Grid extends Mage_Adminhtml_Block_Widget_Grid { + + public function __construct() { + parent::__construct(); + $this->setId('mailgun_event_grid'); + $this->setDefaultSort('timestamp'); + $this->setDefaultDir('ASC'); + $this->setUseAjax(false); + $this->setFilterVisibility(false); + } + + protected function _prepareCollection() { + $collection = Mage::getResourceModel('freelunchlabs_mailgun/event_collection'); + $collection->addFieldToFilter('email_id', Mage::registry('current_email')->getId()); + + $this->setCollection($collection); + return parent::_prepareCollection(); + } + + protected function _prepareColumns() { + + $this->addColumn('event_type', array( + 'header' => 'Event', + 'index' => 'event_type', + 'renderer' => 'FreeLunchLabs_MailGun_Block_Adminhtml_Event_Renderer_Type' + )); + + $this->addColumn('timestamp', array( + 'header' => 'Event Time', + 'index' => 'timestamp', + 'renderer' => 'FreeLunchLabs_MailGun_Block_Adminhtml_Event_Renderer_Timestamp' + )); + + return parent::_prepareColumns(); + } + + public function getRowUrl($row) { + return null; + } + + public function getGridUrl() { + return $this->getUrl('*/emailTracking/emailDetail', array( + '_current' => true, + 'id' => Mage::registry('current_email')->getId() + )); + } + +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Renderer/Timestamp.php b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Renderer/Timestamp.php new file mode 100644 index 0000000..6e46333 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Renderer/Timestamp.php @@ -0,0 +1,10 @@ +<?php +class FreeLunchLabs_MailGun_Block_Adminhtml_Event_Renderer_Timestamp extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract +{ + public function render(Varien_Object $row) + { + $value = $row->getData($this->getColumn()->getIndex()); + $date = Mage::getSingleton('core/date')->date(null, $value); + return Mage::helper('core')->formatDate(new Zend_Date($date), 'medium', true); + } +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Renderer/Type.php b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Renderer/Type.php new file mode 100644 index 0000000..74ed449 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Event/Renderer/Type.php @@ -0,0 +1,9 @@ +<?php +class FreeLunchLabs_MailGun_Block_Adminhtml_Event_Renderer_Type extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract +{ + public function render(Varien_Object $row) + { + $value = $row->getData($this->getColumn()->getIndex()); + return ucwords($value); + } +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Global/Container.php b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Global/Container.php new file mode 100644 index 0000000..210fd15 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Global/Container.php @@ -0,0 +1,13 @@ +<?php + +class FreeLunchLabs_MailGun_Block_Adminhtml_Global_Container extends Mage_Adminhtml_Block_Widget_Grid_Container { + + protected function _construct() { + parent::_construct(); + + $this->_blockGroup = 'freelunchlabs_mailgun'; + $this->_controller = 'adminhtml_global'; + $this->_headerText = false; + + } +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Global/Grid.php b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Global/Grid.php new file mode 100644 index 0000000..dbf0fdf --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Block/Adminhtml/Global/Grid.php @@ -0,0 +1,66 @@ +<?php + +class FreeLunchLabs_MailGun_Block_Adminhtml_Global_Grid extends Mage_Adminhtml_Block_Widget_Grid { + + public function __construct() { + parent::__construct(); + $this->setId('mailgun_global_grid'); + $this->setDefaultSort('date_sent'); + $this->setDefaultDir('ASC'); + $this->setUseAjax(false); + $this->setFilterVisibility(true); + } + + protected function _prepareCollection() { + $collection = Mage::getResourceModel('freelunchlabs_mailgun/email_collection')->getGridCollection(); + + $this->setCollection($collection); + return parent::_prepareCollection(); + } + + protected function _prepareColumns() { + + $this->addColumn('subject', array( + 'header' => 'Subject', + 'type' => 'text', + 'index' => 'subject' + )); + + $this->addColumn('email_address', array( + 'header' => 'Recipient Address', + 'type' => 'email', + 'index' => 'email_address' + )); + + $this->addColumn('mailgun_id', array( + 'header' => 'Mailgun ID', + 'type' => 'text', + 'index' => 'mailgun_id' + )); + + $this->addColumn('current_status', array( + 'header' => 'Latest Status', + 'index' => 'current_status', + 'renderer' => 'FreeLunchLabs_MailGun_Block_Adminhtml_Event_Renderer_Type' + )); + + $this->addColumn('date_sent', array( + 'header' => 'Date Sent', + 'type' => 'datetime', + 'index' => 'date_sent' + )); + + return parent::_prepareColumns(); + } + + public function getRowUrl($row) { + return $this->getUrl('*/emailTracking/emailDetail', array( + 'id' => $row->getId() + )); + } + + public function getGridUrl() { + return $this->getUrl('*/emailtracking'); + } + +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Helper/Data.php b/app/code/community/FreeLunchLabs/MailGun/Helper/Data.php new file mode 100644 index 0000000..8bfb539 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Helper/Data.php @@ -0,0 +1,5 @@ +<?php + +class FreeLunchLabs_MailGun_Helper_Data extends Mage_Core_Helper_Abstract { + +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Model/Email.php b/app/code/community/FreeLunchLabs/MailGun/Model/Email.php new file mode 100644 index 0000000..1f8ed03 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Model/Email.php @@ -0,0 +1,48 @@ +<?php + +class FreeLunchLabs_MailGun_Model_Email extends Mage_Core_Model_Abstract { + + protected function _construct() { + $this->_init('freelunchlabs_mailgun/email'); + } + + public function saveInitialSend($message, $sendResponse) { + $customer = Mage::getModel('customer/customer'); + $customer->setWebsiteId($message->getStore()->getWebsite()->getId()); + $customer->loadByEmail($message->getPrimaryRecipient()); + + if ($customer) { + $this->setCustomerId($customer->getId()); + } + + $this->setEmailAddress($message->getPrimaryRecipient()); + $this->setMailgunId(str_replace(array("<", ">"), "", $sendResponse->id)); + $this->setSubject($message->getSubject()); + $this->setBody($message->getHtmlBody()); + $this->setDateSent(Mage::getSingleton('core/date')->gmtTimestamp()); + $this->save(); + + Mage::getModel('freelunchlabs_mailgun/event')->logEmailEvent($this->getId(), FreeLunchLabs_MailGun_Model_Event::PUSHED, $this); + } + + public function loadByMailgunIdAndRecipient($mailgunId, $recipient) { + $collection = $this->getCollection(); + $collection->addFieldToFilter('mailgun_id', $mailgunId); + $collection->addFieldToFilter('email_address', $recipient); + + return $collection->getFirstItem(); + } + + public function deleteEmailTrackingLogsDays() { + $days = Mage::getStoreConfig('mailgun/events/days'); + + if ($days) { + $this->deleteEmailTrackingLogs($days); + } + } + + public function deleteEmailTrackingLogs($days = false) { + $this->getResource()->deleteEmailTrackingLogs($days); + } + +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Model/Email/Template.php b/app/code/community/FreeLunchLabs/MailGun/Model/Email/Template.php new file mode 100644 index 0000000..6ccdd13 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Model/Email/Template.php @@ -0,0 +1,133 @@ +<?php + +class FreeLunchLabs_MailGun_Model_Email_Template extends Mage_Core_Model_Email_Template { + + var $bcc = null; + var $replyto = null; + var $returnPath = null; //This is not used because MailGun overides it for their internal purposes. + + public function send($email, $name = null, array $variables = array()) { + //Get appropriate store + if(isset($variables['store'])) { + $store = $variables['store']; + } elseif($this->getDesignConfig()->getStore()) { + $store = Mage::getModel('core/store')->load($this->getDesignConfig()->getStore()); + } else { + $store = Mage::app()->getStore(); + } + + if ($store->getConfig('mailgun/general/active')) { + if (!$this->isValidForSend()) { + Mage::logException(new Exception('This letter cannot be sent.')); + return false; + } + + $message = Mage::getModel('freelunchlabs_mailgun/messagebuilder'); + + //Recipient(s) + $emails = array_values((array) $email); + $names = is_array($name) ? $name : (array) $name; + $names = array_values($names); + foreach ($emails as $key => $email) { + if (!isset($names[$key])) { + $names[$key] = substr($email, 0, strpos($email, '@')); + } + } + + $variables['email'] = reset($emails); + $variables['name'] = reset($names); + + //Add To Recipients + $isPrimary = true; + foreach ($emails as $key => $email) { + if($isPrimary) { + //Add primary recipient + $message->setPrimaryRecipient($email); + } + $isPrimary = false; + + $message->addToRecipient($names[$key] . " <" . $email . ">"); + } + + //Subject + $subject = $this->getProcessedTemplateSubject($variables); + $message->setSubject($subject); + + //From Name + $message->setFromAddress($this->getSenderName() . " <" . $this->getSenderEmail() . ">"); + + //Bcc + if (is_array($this->bcc)) { + foreach ($this->bcc as $bcc_email) { + $message->addBccRecipient($bcc_email); + } + } elseif ($this->bcc) { + $message->addBccRecipient($this->bcc); + } + + //Reply To + if (!is_null($this->replyto)) { + $message->setReplyToAddress($this->replyto); + } + + //Message Body + $this->setUseAbsoluteLinks(true); + $processedTemplateBody = $this->getProcessedTemplate($variables, true); + + if ($this->isPlain()) { + $message->setTextBody($processedTemplateBody); + } else { + $message->setHtmlBody($processedTemplateBody); + } + + //Add Unique Args + $message->addCustomData("message_data", array('id' => 123456)); + + //Tag message with type + $message->addTag($this->getTemplateId()); + $message->addTag($store->getConfig('mailgun/general/tag')); + + if($store->getConfig('mailgun/events/opens')) { + $message->setOpenTracking(true); + } + + if($store->getConfig('mailgun/events/clicks')) { + $message->setClickTracking(true); + } + + //Set store + $message->setStore($store); + + //Send it! + try { + Mage::getModel('freelunchlabs_mailgun/mailgun')->send($message); + $this->_mail = null; + } catch (Exception $e) { + $this->_mail = null; + Mage::logException($e); + return false; + } + + return true; + } else { + return parent::send($email, $name, $variables); + } + } + + public function addBcc($bcc) { + $this->bcc = $bcc; + return parent::addBcc($bcc); + } + + public function setReturnPath($email) { + $this->returnPath = $email; + return parent::setReturnPath($email); + + } + + public function setReplyTo($email) { + $this->replyto = $email; + return parent::setReplyTo($email); + } + +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Model/Event.php b/app/code/community/FreeLunchLabs/MailGun/Model/Event.php new file mode 100644 index 0000000..3b65ae6 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Model/Event.php @@ -0,0 +1,36 @@ +<?php + +class FreeLunchLabs_MailGun_Model_Event extends Mage_Core_Model_Abstract { + //Event types + + const PUSHED = "pushed"; + const ACCEPTED = "accepted"; + const REJECTED = "rejected"; + const DELIVERED = "delivered"; + const FAILED = "failed"; + const OPENED = "opened"; + const CLICKED = "clicked"; + const UNSUBSCRIBED = "unsubscribed"; + const COMPLAINED = "complained"; + const STORED = "stored"; + + protected function _construct() { + $this->_init('freelunchlabs_mailgun/event'); + } + + public function logEmailEvent($emailId, $eventType, $email = false) { + $this->setEmailId($emailId); + $this->setEventType($eventType); + $this->setTimestamp(Mage::getSingleton('core/date')->gmtTimestamp()); + $this->save(); + } + + public function loadByTimestampAndEmailId($timestamp, $emailId) { + $collection = $this->getCollection(); + $collection->addFieldToFilter('timestamp', $timestamp); + $collection->addFieldToFilter('email_id', $emailId); + + return $collection->getFirstItem(); + } + +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/InvalidParameter.php b/app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/InvalidParameter.php new file mode 100755 index 0000000..433686a --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/InvalidParameter.php @@ -0,0 +1,5 @@ +<?php + +class FreeLunchLabs_MailGun_Model_Exceptions_InvalidParameter extends \Exception{} + +?> \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/InvalidParameterType.php b/app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/InvalidParameterType.php new file mode 100755 index 0000000..9c4e533 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/InvalidParameterType.php @@ -0,0 +1,5 @@ +<?php + +class FreeLunchLabs_MailGun_Model_Exceptions_InvalidParameterType extends \Exception{} + +?> \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/MissingRequiredMIMEParameters.php b/app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/MissingRequiredMIMEParameters.php new file mode 100755 index 0000000..e4badc8 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/MissingRequiredMIMEParameters.php @@ -0,0 +1,5 @@ +<?php + +class FreeLunchLabs_MailGun_Model_Exceptions_MissingRequiredMIMEParameters extends \Exception{} + +?> \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/TooManyParameters.php b/app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/TooManyParameters.php new file mode 100755 index 0000000..df12fc6 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Model/Exceptions/TooManyParameters.php @@ -0,0 +1,5 @@ +<?php + +class FreeLunchLabs_MailGun_Model_Exceptions_TooManyParameters extends \Exception{} + +?> \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Model/Mailgun.php b/app/code/community/FreeLunchLabs/MailGun/Model/Mailgun.php new file mode 100644 index 0000000..49ade88 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Model/Mailgun.php @@ -0,0 +1,120 @@ +<?php + +class FreeLunchLabs_MailGun_Model_Mailgun extends Mage_Core_Model_Abstract { + + public $apiUrl = "https://api.mailgun.net/v2/"; + + public function mailgunRequest($type, $domain, $apiKey, $data, $method = Zend_Http_Client::GET, $uriOveride = false) { + + $client = new Zend_Http_Client(); + $client->setAuth("api", $apiKey); + $client->setMethod($method); + + if($uriOveride) { + $client->setUri($uriOveride); + } else { + $client->setUri($this->apiUrl . $domain . "/" . $type); + } + + if($method == Zend_Http_Client::POST) { + foreach($data as $key => $value) { + $client->setParameterPost($key, $value); + } + } else { + foreach($data as $key => $value) { + $client->setParameterGet($key, $value); + } + } + + try { + $response = $client->request(); + + if($response->getStatus() == 200) { + return json_decode($response->getBody()); + } else { + throw new Zend_Http_Exception("Error connecting to MailGun API. Returned error code: " . $response->getStatus() . " --- " . $response->getBody()); + } + } catch (Exception $e) { + Mage::logException($e); + return false; + } + } + + public function send($message) { + + $domain = $message->getStore()->getConfig('mailgun/general/domain'); + $apiKey = $message->getStore()->getConfig('mailgun/general/key'); + + $sendResponse = $this->mailgunRequest('messages', $domain, $apiKey, $message->getMessage(), Zend_Http_Client::POST); + + if($message->getStore()->getConfig('mailgun/events/store')) { + Mage::getModel('freelunchlabs_mailgun/email')->saveInitialSend($message, $sendResponse); + } + + return $sendResponse; + } + + public function processEmailEventsForAllStores() { + + $stores = Mage::getModel('core/store')->getCollection(); + + foreach($stores as $store) { + if($store->getConfig('mailgun/events/store')) { + $this->processEmailEventsForSingleStore($store); + } + } + } + + public function processEmailEventsForSingleStore(Mage_Core_Model_Store $store) { + + if($store->getConfig('mailgun/events/store')) { + + $data = array( + 'end' => date("r", time() - 86400), + 'tags' => $store->getConfig('mailgun/general/tag') + ); + + $mailgunEvents = $this->mailgunRequest( + 'events', + $store->getConfig('mailgun/general/domain'), + $store->getConfig('mailgun/general/key'), + $data + ); + + $events = $mailgunEvents->items; + + while (sizeof($mailgunEvents->items) > 0) { + $mailgunEvents = $this->mailgunRequest( + 'events', + $store->getConfig('mailgun/general/domain'), + $store->getConfig('mailgun/general/key'), + $data, + Zend_Http_Client::GET, + $mailgunEvents->paging->next + ); + + $events = array_merge($events, $mailgunEvents->items); + } + + $this->storeEvents($events); + } + } + + public function storeEvents($events) { + foreach($events as $mailgunEvent) { + $email = Mage::getModel('freelunchlabs_mailgun/email')->loadByMailgunIdAndRecipient($mailgunEvent->message->headers->{'message-id'}, $mailgunEvent->recipient); + + if($email->getId()) { + $event = Mage::getModel('freelunchlabs_mailgun/event')->loadByTimestampAndEmailId($mailgunEvent->timestamp, $email->getId()); + + if(!$event->getId()) { + $event->setEmailId($email->getId()); + $event->setEventType($mailgunEvent->event); + $event->setTimestamp($mailgunEvent->timestamp); + $event->save(); + } + } + } + } + +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Model/Messagebuilder.php b/app/code/community/FreeLunchLabs/MailGun/Model/Messagebuilder.php new file mode 100644 index 0000000..5260d03 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Model/Messagebuilder.php @@ -0,0 +1,296 @@ +<?php + +class FreeLunchLabs_MailGun_Model_Messagebuilder extends Varien_Object { + + const API_USER = "api"; + const SDK_USER_AGENT = "freelunchlabs_magento_extension"; + const RECIPIENT_COUNT_LIMIT = 1000; + const CAMPAIGN_ID_LIMIT = 3; + const TAG_LIMIT = 3; + const DEFAULT_TIME_ZONE = "UTC"; + + //Common Exception Messages + const EXCEPTION_INVALID_CREDENTIALS = "Your credentials are incorrect."; + const EXCEPTION_GENERIC_HTTP_ERROR = "An HTTP Error has occurred! Check your network connection and try again."; + const EXCEPTION_MISSING_REQUIRED_PARAMETERS = "The parameters passed to the API were invalid. Check your inputs!"; + const EXCEPTION_MISSING_ENDPOINT = "The endpoint you've tried to access does not exist. Check your URL."; + const TOO_MANY_RECIPIENTS = "You've exceeded the maximum recipient count (1,000) on the to field with autosend disabled."; + const INVALID_PARAMETER_NON_ARRAY = "The parameter you've passed in position 2 must be an array."; + const INVALID_PARAMETER_ATTACHMENT = "Attachments must be passed with an \"@\" preceding the file path. Web resources not supported."; + const INVALID_PARAMETER_INLINE = "Inline images must be passed with an \"@\" preceding the file path. Web resources not supported."; + const TOO_MANY_PARAMETERS_CAMPAIGNS = "You've exceeded the maximum (3) campaigns for a single message."; + const TOO_MANY_PARAMETERS_TAGS = "You've exceeded the maximum (3) tags for a single message."; + const TOO_MANY_PARAMETERS_RECIPIENT = "You've exceeded the maximum recipient count (1,000) on the to field with autosend disabled."; + + protected $message = array(); + protected $variables = array(); + protected $files = array(); + protected $counters = array('recipients' => array('to' => 0, + 'cc' => 0, + 'bcc' => 0), + 'attributes' => array('attachment' => 0, + 'campaign_id' => 0, + 'custom_option' => 0, + 'tag' => 0) + ); + + protected function safeGet($params, $key, $default) { + if (array_key_exists($key, $params)) { + return $params[$key]; + } + return $default; + } + + protected function getFullName($params) { + if (array_key_exists("first", $params)) { + $first = $this->safeGet($params, "first", ""); + $last = $this->safeGet($params, "last", ""); + return trim("$first $last"); + } + return $this->safeGet($params, "full_name", ""); + } + + protected function parseAddress($address, $variables) { + if (!is_array($variables)) { + return $address; + } + $fullName = $this->getFullName($variables); + if ($fullName != null) { + return "'$fullName' <$address>"; + } + return $address; + } + + protected function addRecipient($headerName, $address, $variables) { + $compiledAddress = $this->parseAddress($address, $variables); + + if (isset($this->message[$headerName])) { + array_push($this->message[$headerName], $compiledAddress); + } elseif ($headerName == "h:reply-to") { + $this->message[$headerName] = $compiledAddress; + } else { + $this->message[$headerName] = array($compiledAddress); + } + if (array_key_exists($headerName, $this->counters['recipients'])) { + $this->counters['recipients'][$headerName] += 1; + } + } + + public function addToRecipient($address, $variables = null) { + if ($this->counters['recipients']['to'] > self::RECIPIENT_COUNT_LIMIT) { + throw new FreeLunchLabs_MailGun_Model_Exceptions_TooManyParameters(TOO_MANY_PARAMETERS_RECIPIENT); + } + $this->addRecipient("to", $address, $variables); + return end($this->message['to']); + } + + public function addCcRecipient($address, $variables = null) { + if ($this->counters['recipients']['cc'] > self::RECIPIENT_COUNT_LIMIT) { + throw new FreeLunchLabs_MailGun_Model_Exceptions_TooManyParameters(TOO_MANY_PARAMETERS_RECIPIENT); + } + $this->addRecipient("cc", $address, $variables); + return end($this->message['cc']); + } + + public function addBccRecipient($address, $variables = null) { + if ($this->counters['recipients']['bcc'] > self::RECIPIENT_COUNT_LIMIT) { + throw new FreeLunchLabs_MailGun_Model_Exceptions_TooManyParameters(TOO_MANY_PARAMETERS_RECIPIENT); + } + $this->addRecipient("bcc", $address, $variables); + return end($this->message['bcc']); + } + + public function setFromAddress($address, $variables = null) { + $this->addRecipient("from", $address, $variables); + return $this->message['from']; + } + + public function setReplyToAddress($address, $variables = null) { + $this->addRecipient("h:reply-to", $address, $variables); + return $this->message['h:reply-to']; + } + + public function setSubject($subject = NULL) { + if ($subject == NULL || $subject == "") { + $subject = " "; + } + $this->message['subject'] = $subject; + return $this->message['subject']; + } + + public function getSubject() { + return $this->message['subject']; + } + + public function addCustomHeader($headerName, $headerData) { + if (!preg_match("/^h:/i", $headerName)) { + $headerName = "h:" . $headerName; + } + $this->message[$headerName] = array($headerData); + return $this->message[$headerName]; + } + + public function setTextBody($textBody) { + if ($textBody == NULL || $textBody == "") { + $textBody = " "; + } + $this->message['text'] = $textBody; + return $this->message['text']; + } + + public function setHtmlBody($htmlBody) { + if ($htmlBody == NULL || $htmlBody == "") { + $htmlBody = " "; + } + $this->message['html'] = $htmlBody; + return $this->message['html']; + } + + public function getHtmlBody() { + return $this->message['html']; + } + + public function addAttachment($attachmentPath, $attachmentName = null) { + if (preg_match("/^@/", $attachmentPath)) { + if (isset($this->files["attachment"])) { + $attachment = array('filePath' => $attachmentPath, + 'remoteName' => $attachmentName); + array_push($this->files["attachment"], $attachment); + } else { + $this->files["attachment"] = array(array('filePath' => $attachmentPath, + 'remoteName' => $attachmentName)); + } + return true; + } else { + throw new FreeLunchLabs_MailGun_Model_Exceptions_InvalidParameter(self::INVALID_PARAMETER_ATTACHMENT); + } + } + + public function addInlineImage($inlineImagePath, $inlineImageName = null) { + if (preg_match("/^@/", $inlineImagePath)) { + if (isset($this->files['inline'])) { + $inlineAttachment = array('filePath' => $inlineImagePath, + 'remoteName' => $inlineImageName); + array_push($this->files['inline'], $inlineAttachment); + } else { + $this->files['inline'] = array(array('filePath' => $inlineImagePath, + 'remoteName' => $inlineImageName)); + } + return true; + } else { + throw new FreeLunchLabs_MailGun_Model_Exceptions_InvalidParameter(self::INVALID_PARAMETER_INLINE); + } + } + + public function setTestMode($testMode) { + if (filter_var($testMode, self::FILTER_VALIDATE_BOOLEAN)) { + $testMode = "yes"; + } else { + $testMode = "no"; + } + $this->message['o:testmode'] = $testMode; + return $this->message['o:testmode']; + } + + public function addCampaignId($campaignId) { + if ($this->counters['attributes']['campaign_id'] < self::CAMPAIGN_ID_LIMIT) { + if (isset($this->message['o:campaign'])) { + array_push($this->message['o:campaign'], $campaignId); + } else { + $this->message['o:campaign'] = array($campaignId); + } + $this->counters['attributes']['campaign_id'] += 1; + return $this->message['o:campaign']; + } else { + throw new FreeLunchLabs_MailGun_Model_Exceptions_TooManyParameters(self::TOO_MANY_PARAMETERS_CAMPAIGNS); + } + } + + public function addTag($tag) { + if ($this->counters['attributes']['tag'] < self::TAG_LIMIT) { + if (isset($this->message['o:tag'])) { + array_push($this->message['o:tag'], $tag); + } else { + $this->message['o:tag'] = array($tag); + } + $this->counters['attributes']['tag'] += 1; + return $this->message['o:tag']; + } else { + throw new FreeLunchLabs_MailGun_Model_Exceptions_TooManyParameters(self::TOO_MANY_PARAMETERS_TAGS); + } + } + + public function setDkim($enabled) { + if (filter_var($enabled, FILTER_VALIDATE_BOOLEAN)) { + $enabled = "yes"; + } else { + $enabled = "no"; + } + $this->message["o:dkim"] = $enabled; + return $this->message["o:dkim"]; + } + + public function setOpenTracking($enabled) { + if (filter_var($enabled, FILTER_VALIDATE_BOOLEAN)) { + $enabled = "yes"; + } else { + $enabled = "no"; + } + $this->message['o:tracking-opens'] = $enabled; + return $this->message['o:tracking-opens']; + } + + public function setClickTracking($enabled) { + if (filter_var($enabled, FILTER_VALIDATE_BOOLEAN)) { + $enabled = "yes"; + } elseif ($enabled == "html") { + $enabled = "html"; + } else { + $enabled = "no"; + } + $this->message['o:tracking-clicks'] = $enabled; + return $this->message['o:tracking-clicks']; + } + + public function setDeliveryTime($timeDate, $timeZone = NULL) { + if (isset($timeZone)) { + $timeZoneObj = new DateTimeZone("$timeZone"); + } else { + $timeZoneObj = new DateTimeZone(self::DEFAULT_TIME_ZONE); + } + + $dateTimeObj = new DateTime($timeDate, $timeZoneObj); + $formattedTimeDate = $dateTimeObj->format(DateTime::RFC2822); + $this->message['o:deliverytime'] = $formattedTimeDate; + return $this->message['o:deliverytime']; + } + + public function addCustomData($customName, $data) { + if (is_array($data)) { + $jsonArray = json_encode($data); + $this->message['v:' . $customName] = $jsonArray; + return $this->message['v:' . $customName]; + } else { + throw new FreeLunchLabs_MailGun_Model_Exceptions_InvalidParameter(self::INVALID_PARAMETER_NON_ARRAY); + } + } + + public function addCustomParameter($parameterName, $data) { + if (isset($this->message[$parameterName])) { + array_push($this->message[$parameterName], $data); + return $this->message[$parameterName]; + } else { + $this->message[$parameterName] = array($data); + return $this->message[$parameterName]; + } + } + + public function getMessage() { + return $this->message; + } + + public function getFiles() { + return $this->files; + } + +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Model/Resource/Email.php b/app/code/community/FreeLunchLabs/MailGun/Model/Resource/Email.php new file mode 100644 index 0000000..c7926f5 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Model/Resource/Email.php @@ -0,0 +1,26 @@ +<?php + +class FreeLunchLabs_MailGun_Model_Resource_Email extends Mage_Core_Model_Resource_Db_Abstract +{ + protected function _construct() + { + $this->_init('freelunchlabs_mailgun/email', 'id'); + } + + public function deleteEmailTrackingLogs($days = false) { + if($days) { + $daysPrior = date("Y-m-d H:i:s", Mage::getModel('core/date')->timestamp(time() - (86400 * $days))); + $where = " WHERE date_sent < '{$daysPrior}'"; + } else { + $where = ""; + } + + $query = "DELETE FROM {$this->getMainTable()}" . $where; + + Mage::getSingleton('core/resource') + ->getConnection('core_write') + ->query($query); + + } + +} diff --git a/app/code/community/FreeLunchLabs/MailGun/Model/Resource/Email/Collection.php b/app/code/community/FreeLunchLabs/MailGun/Model/Resource/Email/Collection.php new file mode 100644 index 0000000..3e0b54b --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Model/Resource/Email/Collection.php @@ -0,0 +1,38 @@ +<?php + +class FreeLunchLabs_MailGun_Model_Resource_Email_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract +{ + protected function _construct() + { + parent::_construct(); + + $this->_init('freelunchlabs_mailgun/email'); + } + + public function getGridCollection() { + //Fields + $this->addFieldToSelect('id'); + $this->addFieldToSelect('subject'); + $this->addFieldToSelect('email_address'); + $this->addFieldToSelect('mailgun_id'); + $this->addFieldToSelect('date_sent'); + $this->addFieldToSelect('customer_id'); + + //Get latest status + $this->getSelect()->joinLeft( + array('me1' => Mage::getResourceModel('freelunchlabs_mailgun/event')->getMainTable()), + 'main_table.id = me1.email_id', + 'event_type as current_status' + ); + + $this->getSelect()->joinLeft( + array('me2' => Mage::getResourceModel('freelunchlabs_mailgun/event')->getMainTable()), + '(main_table.id = me2.email_id AND (me1.timestamp < me2.timestamp OR me1.timestamp = me2.timestamp AND me1.id < me2.id))', + false + ); + + $this->getSelect()->where('me2.id IS NULL'); + + return $this; + } +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/Model/Resource/Event.php b/app/code/community/FreeLunchLabs/MailGun/Model/Resource/Event.php new file mode 100644 index 0000000..8296cd2 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Model/Resource/Event.php @@ -0,0 +1,10 @@ +<?php + +class FreeLunchLabs_MailGun_Model_Resource_Event extends Mage_Core_Model_Resource_Db_Abstract +{ + protected function _construct() + { + $this->_init('freelunchlabs_mailgun/event', 'id'); + } + +} diff --git a/app/code/community/FreeLunchLabs/MailGun/Model/Resource/Event/Collection.php b/app/code/community/FreeLunchLabs/MailGun/Model/Resource/Event/Collection.php new file mode 100644 index 0000000..3e0cf86 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/Model/Resource/Event/Collection.php @@ -0,0 +1,11 @@ +<?php + +class FreeLunchLabs_MailGun_Model_Resource_Event_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract +{ + protected function _construct() + { + parent::_construct(); + + $this->_init('freelunchlabs_mailgun/event'); + } +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/controllers/Adminhtml/EmailtrackingController.php b/app/code/community/FreeLunchLabs/MailGun/controllers/Adminhtml/EmailtrackingController.php new file mode 100644 index 0000000..4a0af6d --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/controllers/Adminhtml/EmailtrackingController.php @@ -0,0 +1,96 @@ +<?php + +class FreeLunchLabs_MailGun_Adminhtml_EmailtrackingController extends Mage_Adminhtml_Controller_Action { + + protected function _initCustomer($idFieldName = 'id') + { + $this->_title($this->__('Customers'))->_title($this->__('Manage Customers')); + + $customerId = (int) $this->getRequest()->getParam($idFieldName); + $customer = Mage::getModel('customer/customer'); + + if ($customerId) { + $customer->load($customerId); + } + + Mage::register('current_customer', $customer); + return $this; + } + + protected function _initEmail($idFieldName = 'id') { + $emailId = (int) $this->getRequest()->getParam($idFieldName); + $email = Mage::getModel('freelunchlabs_mailgun/email'); + + if ($emailId) { + $email->load($emailId); + } + + Mage::register('current_email', $email); + return $this; + } + + public function emailGridAction() + { + $this->_initCustomer(); + $this->loadLayout(); + $gridBlock = $this->getLayout()->createBlock('freelunchlabs_mailgun/adminhtml_customer_email'); + + $this->getResponse()->setBody($gridBlock->getGridHtml()); + } + + public function indexAction() { + $this->_title($this->__('System'))->_title($this->__('Email Tracking')); + + $this->loadLayout(); + $this->_setActiveMenu('customer'); + $this->renderLayout(); + } + + public function emailDetailAction() { + $this->_title($this->__('System'))->_title($this->__('Email Tracking - Detail')); + + $this->_initEmail(); + + $this->loadLayout(); + $this->_setActiveMenu('customer'); + $this->renderLayout(); + } + + public function getEmailEventsAction() { + Mage::getModel('freelunchlabs_mailgun/mailgun')->processEmailEventsForAllStores(); + + $this->_getSession()->addSuccess( + Mage::helper('adminhtml')->__('Past 24 hours of email events fetched.') + ); + + $this->_redirect('*/*'); + } + + public function emailViewAction() { + $this->_title($this->__('System'))->_title($this->__('Email Tracking - Detail - Email Body')); + $this->_initEmail(); + + $this->getResponse()->setBody(Mage::registry('current_email')->getBody()); + } + + public function deleteEmailTrackingLogsDaysAction() { + Mage::getModel('freelunchlabs_mailgun/email')->deleteEmailTrackingLogsDays(); + + $this->_getSession()->addSuccess( + Mage::helper('adminhtml')->__('Email records older than ' . Mage::getStoreConfig('mailgun/events/days') . ' days were deleted.') + ); + + $this->_redirect('*/*'); + } + + public function deleteEmailTrackingLogsAction() { + Mage::getModel('freelunchlabs_mailgun/email')->deleteEmailTrackingLogs(); + + $this->_getSession()->addSuccess( + Mage::helper('adminhtml')->__('All Email Records Were Deleted.') + ); + + $this->_redirect('*/*'); + } + +} \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/etc/config.xml b/app/code/community/FreeLunchLabs/MailGun/etc/config.xml new file mode 100644 index 0000000..4c378e1 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/etc/config.xml @@ -0,0 +1,151 @@ +<?xml version="1.0"?> +<config> + <modules> + <FreeLunchLabs_MailGun> + <version>1.0.0</version> + </FreeLunchLabs_MailGun> + </modules> + <global> + <models> + <freelunchlabs_mailgun> + <class>FreeLunchLabs_MailGun_Model</class> + <resourceModel>freelunchlabs_mailgun_resource</resourceModel> + </freelunchlabs_mailgun> + <core> + <rewrite> + <email_template>FreeLunchLabs_MailGun_Model_Email_Template</email_template> + </rewrite> + </core> + <freelunchlabs_mailgun_resource> + <class>FreeLunchLabs_MailGun_Model_Resource</class> + <entities> + <email> + <table>mailgun_email_tracking</table> + </email> + <event> + <table>mailgun_email_tracking_event</table> + </event> + </entities> + </freelunchlabs_mailgun_resource> + </models> + <resources> + <mailgun_setup> + <setup> + <module>FreeLunchLabs_MailGun</module> + </setup> + <connection> + <use>core_setup</use> + </connection> + </mailgun_setup> + <mailgun_write> + <connection> + <use>core_write</use> + </connection> + </mailgun_write> + <mailgun_read> + <connection> + <use>core_read</use> + </connection> + </mailgun_read> + </resources> + <helpers> + <mailgun> + <class>FreeLunchLabs_MailGun_Helper</class> + </mailgun> + </helpers> + <blocks> + <freelunchlabs_mailgun> + <class>FreeLunchLabs_MailGun_Block</class> + </freelunchlabs_mailgun> + </blocks> + </global> + <admin> + <routers> + <adminhtml> + <args> + <modules> + <freelunchlabs_mailgun before="Mage_Adminhtml">FreeLunchLabs_MailGun_Adminhtml</freelunchlabs_mailgun> + </modules> + </args> + </adminhtml> + </routers> + </admin> + <adminhtml> + <menu> + <customer> + <children> + <cloudfront translate="title" module="mailgun"> + <title>Email Tracking</title> + <sort_order>9999</sort_order> + <action>adminhtml/emailtracking</action> + </cloudfront> + </children> + </customer> + </menu> + <acl> + <resources> + <admin> + <children> + <system> + <children> + <config> + <children> + <mailgun translate="title" module="mailgun"> + <title>MailGun Configuration</title> + <sort_order>50</sort_order> + </mailgun> + </children> + </config> + <emailtracking> + <title>Email Tracking</title> + <sort_order>70</sort_order> + </emailtracking> + </children> + </system> + </children> + </admin> + </resources> + </acl> + <layout> + <updates> + <mailgun> + <file>mailgun.xml</file> + </mailgun> + </updates> + </layout> + </adminhtml> + <default> + <mailgun> + <general> + <active>0</active> + <tag>magento-store</tag> + </general> + <events> + <store>1</store> + <days>30</days> + <clicks>1</clicks> + <opens>1</opens> + </events> + </mailgun> + </default> + <crontab> + <jobs> + <freelunchlabs_purgelogs> + <schedule> + <cron_expr>0,15,30,45 * * * *</cron_expr> + </schedule> + <run> + <model>freelunchlabs_mailgun/email::deleteEmailTrackingLogsDays</model> + </run> + </freelunchlabs_purgelogs> + <freelunchlabs_processevents> + <schedule> + <cron_expr>0,15,30,45 * * * *</cron_expr> + </schedule> + <run> + <model>freelunchlabs_mailgun/mailgun::processEmailEventsForAllStores</model> + </run> + </freelunchlabs_processevents> + </jobs> + </crontab> +</config> \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/etc/system.xml b/app/code/community/FreeLunchLabs/MailGun/etc/system.xml new file mode 100644 index 0000000..ca2a4b9 --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/etc/system.xml @@ -0,0 +1,111 @@ +<?xml version="1.0"?> +<config> + <sections> + <mailgun translate="label" module="mailgun"> + <class>separator-top</class> + <label>MailGun Configuration</label> + <tab>general</tab> + <sort_order>110</sort_order> + <show_in_default>1</show_in_default> + <show_in_website>1</show_in_website> + <show_in_store>1</show_in_store> + <groups> + <general translate="label comment"> + <label>MailGun Configuration</label> + <frontend_type>text</frontend_type> + <sort_order>1</sort_order> + <show_in_default>1</show_in_default> + <show_in_website>0</show_in_website> + <show_in_store>1</show_in_store> + <fields> + <active translate="label comment"> + <label>Enabled MailGun For Sending Emails</label> + <frontend_type>select</frontend_type> + <source_model>adminhtml/system_config_source_yesno</source_model> + <sort_order>1</sort_order> + <show_in_default>1</show_in_default> + <show_in_website>1</show_in_website> + <show_in_store>1</show_in_store> + </active> + <key translate="label comment"> + <label>MailGun API Key</label> + <frontend_type>password</frontend_type> + <sort_order>3</sort_order> + <show_in_default>1</show_in_default> + <show_in_website>1</show_in_website> + <show_in_store>1</show_in_store> + <comment>Your MailGun API Key</comment> + </key> + <domain translate="label comment"> + <label>Sending Domain</label> + <frontend_type>text</frontend_type> + <sort_order>4</sort_order> + <show_in_default>1</show_in_default> + <show_in_website>1</show_in_website> + <show_in_store>1</show_in_store> + <comment>Your verified sending domain. For example, "example.com", "email.example.com"</comment> + </domain> + <tag translate="label comment"> + <label>Email Tag</label> + <frontend_type>text</frontend_type> + <sort_order>5</sort_order> + <show_in_default>1</show_in_default> + <show_in_website>1</show_in_website> + <show_in_store>1</show_in_store> + <comment>For Administrative purposes only. This tag is used for filtering emails in MailGun.</comment> + </tag> + </fields> + </general> + <events translate="label"> + <label>Email Tracking</label> + <frontend_type>text</frontend_type> + <sort_order>2</sort_order> + <show_in_default>1</show_in_default> + <show_in_website>1</show_in_website> + <show_in_store>1</show_in_store> + <fields> + <store translate="label comment"> + <label>Track All Emails</label> + <frontend_type>select</frontend_type> + <source_model>adminhtml/system_config_source_yesno</source_model> + <sort_order>1</sort_order> + <show_in_default>1</show_in_default> + <show_in_website>1</show_in_website> + <show_in_store>1</show_in_store> + <comment>Keep a record of all transactional emails sent.</comment> + </store> + <days translate="label comment"> + <label>Days To Save Email Records</label> + <frontend_type>text</frontend_type> + <sort_order>2</sort_order> + <show_in_default>1</show_in_default> + <show_in_website>0</show_in_website> + <show_in_store>0</show_in_store> + <comment>Days to save email records. Leave blank for indefinitely.</comment> + </days> + <clicks translate="label comment"> + <label>Enabled Click Tracking</label> + <frontend_type>select</frontend_type> + <source_model>adminhtml/system_config_source_yesno</source_model> + <sort_order>3</sort_order> + <show_in_default>1</show_in_default> + <show_in_website>1</show_in_website> + <show_in_store >1</show_in_store> + <comment>Keep track of every time a recipient clicks on links in your messages. Links will be overwritten and pointed to MailGun servers so they can track clicks.</comment> + </clicks> + <opens translate="label comment"> + <label>Enabled Open Tracking</label> + <frontend_type>select</frontend_type> + <source_model>adminhtml/system_config_source_yesno</source_model> + <sort_order>4</sort_order> + <show_in_default>1</show_in_default> + <show_in_website>1</show_in_website> + <show_in_store>1</show_in_store> + <comment>Keep track of every time a recipient opens your messages. Opens are tracked by including a transparent .png file in you email.</comment> + </opens> + </fields> + </events> + </groups> + </mailgun> + </sections> +</config> \ No newline at end of file diff --git a/app/code/community/FreeLunchLabs/MailGun/sql/mailgun_setup/mysql4-install-1.0.0.php b/app/code/community/FreeLunchLabs/MailGun/sql/mailgun_setup/mysql4-install-1.0.0.php new file mode 100644 index 0000000..0fd7ebc --- /dev/null +++ b/app/code/community/FreeLunchLabs/MailGun/sql/mailgun_setup/mysql4-install-1.0.0.php @@ -0,0 +1,33 @@ +<?php + +$installer = $this; + +$installer->startSetup(); + +$installer->run(" + +-- DROP TABLE IF EXISTS {$this->getTable('freelunchlabs_mailgun/email')}; +CREATE TABLE {$this->getTable('freelunchlabs_mailgun/email')} ( + `id` int(11) unsigned NOT NULL auto_increment, + `customer_id` int(11) NULL, + `mailgun_id` varchar(255) NOT NULL default '', + `email_address` varchar(255) NOT NULL default '', + `subject` text, + `body` text, + `date_sent` timestamp NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- DROP TABLE IF EXISTS {$this->getTable('freelunchlabs_mailgun/event')}; +CREATE TABLE {$this->getTable('freelunchlabs_mailgun/event')} ( + `id` int(11) unsigned NOT NULL auto_increment, + `email_id` int(11) NULL, + `event_type` varchar(255) NOT NULL default '', + `timestamp` varchar(255) + PRIMARY KEY (`id`), + CONSTRAINT `fk_event_tracking` FOREIGN KEY (`email_id`) REFERENCES `{$this->getTable('freelunchlabs_mailgun/email')}` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +"); + +$installer->endSetup(); \ No newline at end of file diff --git a/app/design/adminhtml/default/default/layout/mailgun.xml b/app/design/adminhtml/default/default/layout/mailgun.xml new file mode 100644 index 0000000..dfe2f66 --- /dev/null +++ b/app/design/adminhtml/default/default/layout/mailgun.xml @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<layout> + <adminhtml_customer_edit> + <reference name="customer_edit_tabs"> + <action method="addTab"> + <name>customer_tab_mailgun</name> + <block>freelunchlabs_mailgun/adminhtml_customer_tab_mailgun</block> + </action> + </reference> + </adminhtml_customer_edit> + <adminhtml_emailtracking_index> + <reference name="content"> + <block type="freelunchlabs_mailgun/adminhtml_emailtracking" name="emailtracking" template="mailgun/globalemailgrid.phtml"></block> + </reference> + </adminhtml_emailtracking_index> + <adminhtml_emailtracking_emaildetail> + <reference name="content"> + <block type="freelunchlabs_mailgun/adminhtml_emailtracking" name="emailtracking" template="mailgun/emaildetail.phtml"></block> + </reference> + </adminhtml_emailtracking_emaildetail> +</layout> \ No newline at end of file diff --git a/app/design/adminhtml/default/default/template/mailgun/customer/tab/tab.phtml b/app/design/adminhtml/default/default/template/mailgun/customer/tab/tab.phtml new file mode 100644 index 0000000..84dd32d --- /dev/null +++ b/app/design/adminhtml/default/default/template/mailgun/customer/tab/tab.phtml @@ -0,0 +1 @@ +<?php echo $this->getGrid(); ?> \ No newline at end of file diff --git a/app/design/adminhtml/default/default/template/mailgun/emaildetail.phtml b/app/design/adminhtml/default/default/template/mailgun/emaildetail.phtml new file mode 100644 index 0000000..eff3597 --- /dev/null +++ b/app/design/adminhtml/default/default/template/mailgun/emaildetail.phtml @@ -0,0 +1,90 @@ +<?php $_emailDetail = $this->getEmailDetail(); ?> +<div class="content-header"> + <table cellspacing="0"> + <tr> + <td> + <h3><?php echo Mage::helper('adminhtml')->__('Email Details') ?></h3> + </td> + <td class="form-buttons"> + <?php echo $this->getBackButtonHtml(); ?> + <?php echo $this->getViewEmailBodyButtonHtml($_emailDetail->getId()); ?> + </td> + </tr> + </table> +</div> +<div class="box-left"> + <div class="entry-edit"> + <div class="entry-edit-head"> + <h4 class="icon-head head-account"><?php echo Mage::helper('adminhtml')->__('Email Information') ?></h4> + </div> + <div class="fieldset"> + <table cellspacing="0" class="form-list"> + <tbody> + <tr> + <td class="label"><label><?php echo Mage::helper('adminhtml')->__('Date Sent') ?></label></td> + <td class="value"><strong><?php echo Mage::helper('core')->formatDate($_emailDetail->getDateSent(), 'full', true); ?></strong></td> + </tr> + <tr> + <td class="label"><label><?php echo Mage::helper('adminhtml')->__('Subject') ?></label></td> + <td class="value"><strong><?php echo $_emailDetail->getSubject(); ?></strong></td> + </tr> + <tr> + <td class="label"><label><?php echo Mage::helper('adminhtml')->__('Mailgun ID') ?></label></td> + <td class="value"><strong><?php echo $_emailDetail->getMailgunId(); ?></strong></td> + </tr> + <tr> + <td class="label"><label><?php echo Mage::helper('adminhtml')->__('Recipient') ?></label></td> + <td class="value"><strong><?php echo $_emailDetail->getEmailAddress(); ?></strong></td> + </tr> + </tbody> + </table> + </div> + </div> +</div> +<div class="box-right"> + <div class="entry-edit"> + <div class="entry-edit-head"> + <h4 class="icon-head head-account"><?php echo Mage::helper('adminhtml')->__('Customer Information') ?></h4> + </div> + <div class="fieldset"> + <?php if($_emailDetail->getCustomer()): ?> + <table cellspacing="0" class="form-list"> + <tbody> + <tr> + <td class="label"><label><?php echo Mage::helper('adminhtml')->__('Customer') ?></label></td> + <td class="value"> + <a href="<?php echo $this->getEditCustomerUrl($_emailDetail->getCustomer()->getId()); ?>" title="Edit Customer"> + <strong><?php echo $_emailDetail->getCustomer()->getName(); ?></strong> + </a> + </td> + </tr> + <tr> + <td class="label"><label><?php echo Mage::helper('adminhtml')->__('Store') ?></label></td> + <td class="value"><strong><?php echo $_emailDetail->getCustomer()->getStore()->getName(); ?></strong></td> + </tr> + <tr> + <td class="label"><label><?php echo Mage::helper('adminhtml')->__('Customer Group') ?></label></td> + <td class="value"><strong><?php echo $this->getCustomerGroupName($_emailDetail->getCustomer()->getGroupId()); ?></strong></td> + </tr> + <tr> + <td class="label"><label><?php echo Mage::helper('adminhtml')->__('Customer Since') ?></label></td> + <td class="value"><strong><?php echo $this->formatCustomerCreateDate($_emailDetail->getCustomer()->getCreatedAt()); ?></strong></td> + </tr> + </tbody> + </table> + <?php else: ?> + <p>No Customer Data Available.</p> + <?php endif; ?> + </div> + </div> +</div> +<div class="content-header"> + <table cellspacing="0"> + <tr> + <td> + <h3><?php echo Mage::helper('adminhtml')->__('Email Events') ?></h3> + </td> + </tr> + </table> +</div> +<?php echo $this->getLayout()->createBlock('freelunchlabs_mailgun/adminhtml_event_container')->getGridHtml(); ?> diff --git a/app/design/adminhtml/default/default/template/mailgun/globalemailgrid.phtml b/app/design/adminhtml/default/default/template/mailgun/globalemailgrid.phtml new file mode 100644 index 0000000..d3a8452 --- /dev/null +++ b/app/design/adminhtml/default/default/template/mailgun/globalemailgrid.phtml @@ -0,0 +1,15 @@ +<div class="content-header"> + <table cellspacing="0"> + <tr> + <td> + <h3><?php echo Mage::helper('adminhtml')->__('Email Activity') ?></h3> + </td> + <td class="form-buttons"> + <?php echo $this->getFetch24HoursOfEmailActivityButton(); ?> + <?php echo $this->getDeleteEmailTrackingLogsDaysButton(); ?> + <?php echo $this->getDeleteAllEmailTrackingLogsButton(); ?> + </td> + </tr> + </table> +</div> +<?php echo $this->getLayout()->createBlock('freelunchlabs_mailgun/adminhtml_global_container')->getGridHtml(); ?> \ No newline at end of file diff --git a/app/etc/modules/FreeLunchLabs_MailGun.xml b/app/etc/modules/FreeLunchLabs_MailGun.xml new file mode 100644 index 0000000..b1e245f --- /dev/null +++ b/app/etc/modules/FreeLunchLabs_MailGun.xml @@ -0,0 +1,9 @@ +<?xml version="1.0"?> +<config> + <modules> + <FreeLunchLabs_MailGun> + <active>true</active> + <codePool>community</codePool> + </FreeLunchLabs_MailGun> + </modules> +</config> -- GitLab