diff --git a/extension/Documentation/UsersManual/Index.rst b/extension/Documentation/UsersManual/Index.rst index 32d6b4a8da4895a74e7298b3d5d30d1af66e9607..d6f84c44e2166bb848bf5b8ca74e5226caf512da 100644 --- a/extension/Documentation/UsersManual/Index.rst +++ b/extension/Documentation/UsersManual/Index.rst @@ -261,6 +261,7 @@ Store: *FORM* - F * Formelements who will be rerendered, after a parent element has been changed by the user. * Formelement actions, before saving the form. * Values will be sanitized by the class configured in corresponding the formelement. By default, the sanitize class is `alnumx`. + +-------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+ | Name | Explanation | +=========================+============================================================================================================================================+ @@ -610,9 +611,9 @@ Class: Native | | 'container') | | +---------------+-----------------------------+---------------------------------------------------------------------------------------------------+ |type | enum('checkbox', 'date', 'time', 'datetime', 'dateJQW', 'datetimeJQW', 'extra', 'gridJQW', 'text', 'editor', 'note', | -| | 'password', 'radio', 'select', 'subrecord', 'upload', 'fieldset', 'pill', 'beforeLoad', 'beforeSave', | +| | 'password', 'radio', 'select', 'subrecord', 'upload', 'fieldset', 'pill', 'beforeLoad', 'beforeSave', | | | 'beforeInsert', 'beforeUpdate', 'beforeDelete', 'afterLoad', 'afterSave', 'afterInsert', 'afterUpdate', 'afterDelete', | -| | 'sendmail') | +| | 'sendMail') | +---------------+-----------------------------+---------------------------------------------------------------------------------------------------+ |checkType | enum('min|max', 'pattern', | | | | 'number', 'email') | | @@ -658,7 +659,7 @@ Class: Native | | | disabled. Group Access: FE-Groups. User will be assigned to FE-Groups and the form defintion | | | | reference such FE-groups. Easy way of granting permission. | +---------------+-----------------------------+---------------------------------------------------------------------------------------------------+ -|deleted | string |'yes'|'no'. | +|deleted | string | 'yes'|'no'. | +---------------+-----------------------------+---------------------------------------------------------------------------------------------------+ |modified | timestamp |updated autmatically through stored procedure | +---------------+-----------------------------+---------------------------------------------------------------------------------------------------+ @@ -1122,8 +1123,21 @@ Types: Type: sendmail ^^^^^^^^^^^^^^ -* Send mail(s) on request. -* respects 'processRow' +* Send mail(s) after saving the record. + +* FormElement.'''value''': Body of the email. + +* FormElement.’‘’parameter’‘’: + + * ‘’‘sendMailTo‘’‘ - Comma-separated list of receiver email addresses. Optional: 'realname <john@doe.com> + * ‘’‘sendMailCc‘’‘ - Comma-separated list of receiver email addresses. Optional: 'realname <john@doe.com> + * ‘’‘sendMailBcc‘’‘ - Comma-separated list of receiver email addresses. Optional: 'realname <john@doe.com> + * ‘’‘sendMailFrom‘’‘ - Sender of the email. Optional: 'realname <john@doe.com>' + * ‘’‘sendMailSubject‘’‘ - Subject of the email + * ‘’‘sendMailReplyTo‘’‘ - Reply this email address. Optional: 'realname <john@doe.com>' + * ‘’‘sendMailFlagAutoSubmit‘’‘ - **on|off** - If 'on', the mail contains the header 'Auto-Submitted: auto-send' - suppress OoO replies + * ‘’‘sendMailGrId‘’‘ - Will be copied to the mailLog record. Helps to setup specific logfile queries + * ‘’‘sendMailXId‘’‘ - Will be copied to the mailLog record. Helps to setup specific logfile queries .. _dynamic-update: @@ -1140,10 +1154,11 @@ The following fields will be recalculated during 'Dynamic Update' To make a form dynamic: -* Mark all FormElements with {dynamic update}=enabled, which should send **or** receive a 'do update' signal. -* Define the receiving FormElements in a way, that they will interpret the recent user change. The form variable of the - specific sender FormElement `{{<sender element>:F:<sanitize>}} should be part of one of the above fields to get an - impact. E.g.: :: + * Mark all FormElements with {dynamic update}=enabled, which should send **or** receive a 'do update' signal. + * Define the receiving FormElements in a way, that they will interpret the recent user change. The form variable of the + specific sender FormElement `{{<sender element>:F:<sanitize>}}` should be part of one of the above fields to get an + impact. E.g.: + :: [receiving formElement].parameter: itemList={{ SELECT IF({{carPriceRange:FE:alnumx}}='expensive','Ferrari,Tesla,Jaguar','General Motors,Honda,Seat,Fiat') }} @@ -1679,7 +1694,7 @@ The colum name is composed of the string *page* and a trailing character to spec .. +---------------+-----------------------------------------------+-------------------------------------+----------------------------------------------+ -| column name | Purpose | default value of question parameter | Mandatory parameters | +| column name | Purpose |default value of question parameter | Mandatory parameters | +===============+===============================================+=====================================+==============================================+ |_page |Internal link without a grafic |empty |p:<pageId>[¶m] | +---------------+-----------------------------------------------+-------------------------------------+----------------------------------------------+ @@ -1857,29 +1872,41 @@ Easily create Email links. Column: _sendmail ^^^^^^^^^^^^^^^^^ -Send simple plain text emails. Every mail will be logged in the mail log. The logfile can be configured in ext_localconf.php via $TYPO3_CONF_VARS[$_EXTKEY]['log']['mail']. +<TO:email[,email]>|<FROM:email>|<subject>|<body>|[<REPLY-TO:email>]|[<flag autosubmit: on /off>]|[<grid>]|[xId]|<CC:email[,email]>|<BCC:email[,email]> + + +Send text emails. Every mail will be logged in the table `mailLog`. **Syntax** :: - - SELECT "receiver@domain.com[:john doe],receiver2@domain.com[:jane doe]|sender@domain.com[:willi wutzmann]|subject|body" AS _sendmail + SELECT "john@doe.com|jane@doe.com|Reminder tomorrow|Please dont miss the meeting tomorrow" AS _sendmail .. - - +------------------------------------------------------------+------------------------------------------------------------------------------------------+------------+ |**Parameter** |**Description** |**Required**| +============================================================+==========================================================================================+============+ -|receiver@domain.com[:johndoe],receiver2@domain.com[:janedoe]|Comma-separated list of Email-receiver(s). An optional name can be added using a colon (:)| | +|TO:email[,email] |Comma-separated list of receiver email addresses. Optional: `realname <john@doe.com>` | yes | ++------------------------------------------------------------+------------------------------------------------------------------------------------------+------------+ +|FROM:email |Sender of the email. Optional: 'realname <john@doe.com>' | yes | ++------------------------------------------------------------+------------------------------------------------------------------------------------------+------------+ +|subject |Subject of the email | yes | ++------------------------------------------------------------+------------------------------------------------------------------------------------------+------------+ +|body |Message | yes | +------------------------------------------------------------+------------------------------------------------------------------------------------------+------------+ -|sender@domain.com[:williwutzmann] |Sender of the email. An optional name can be added using a colon (:) | | +|REPLY-TO:email |Email address to reply to (if different from sender) | | +------------------------------------------------------------+------------------------------------------------------------------------------------------+------------+ -|subject |Subject of the email | | +|flagAutoSubmit 'on' / 'off' |If 'on', the mail contains the header 'Auto-Submitted: auto-send' - suppress OoO replies | | +------------------------------------------------------------+------------------------------------------------------------------------------------------+------------+ -|body |Message | | +|grId |Will be copied to the mailLog record. Helps to setup specific logfile queries | | ++------------------------------------------------------------+------------------------------------------------------------------------------------------+------------+ +|xId |Will be copied to the mailLog record. Helps to setup specific logfile queries | | ++------------------------------------------------------------+------------------------------------------------------------------------------------------+------------+ +|CC:email[,email] |Comma-separated list of receiver email addresses. Optional: 'realname <john@doe.com>' | | ++------------------------------------------------------------+------------------------------------------------------------------------------------------+------------+ +|BCC:email[,email] |Comma-separated list of receiver email addresses. Optional: 'realname <john@doe.com>' | | +------------------------------------------------------------+------------------------------------------------------------------------------------------+------------+ @@ -1901,50 +1928,13 @@ This will send an email with subject *Latest News* from company@example.com to j :: - 10.sql = SELECT "customer1@example.com, customer2@example.com|company@example.com|Latest News|The new version is now available." AS _sendmail + 10.sql = SELECT "customer1@example.com,Firstname Lastname <customer2@example.com>, Firstname Lastname <customer3@example.com>|company@example.com|Latest News|The new version is now available.|sales@example.com|on|101|222|ceo@example.com|backup@example.com" AS _sendmail .. - - -This will send an email with subject *Latest news* from company@example.com to customer1@example.com and to customer2@example.com. - -Column: _advancedmail -^^^^^^^^^^^^^^^^^^^^^ - -Send plain text/html emails. This is identical to ?t#Column:_sendmail, but allows to additionaly set the cc:, bcc: and reply-to: -headers. Every mail will be logged in the mail log. The logfile can be configured in ext_localconf.php via -$TYPO3_CONF_VARS[$_EXTKEY]['log']['mail']. - -**Syntax** - -:: - - - SELECT "receiver@domain.com[:john doe],receiver2@domain.com[:jane doe]|sender@domain.com[:willi wutzmann]|subject|cc1@domain.com[:willi wutzmann]|bcc1@domain.com[:george wutzmann]|replyto@domain.com[:Support-Desk]|format|body" AS _sendmail - -.. - - - -+------------------------------------------------------------+----------------------------------------------------------------------------------------------+------------+ -|**Parameter** |**Description** |**required**| -+============================================================+==============================================================================================+============+ -|receiver@domain.com[:johndoe],receiver2@domain.com[:janedoe]|Comma-separated list of Email-receiver(s). An optional name can be added using a colon (:) | | -+------------------------------------------------------------+----------------------------------------------------------------------------------------------+------------+ -|sender@domain.com[:williwutzmann] |Sender of the email. An optional name can be added using a colon (:) | | -+------------------------------------------------------------+----------------------------------------------------------------------------------------------+------------+ -|subject |Subject of the email | | -+------------------------------------------------------------+----------------------------------------------------------------------------------------------+------------+ -|cc1@domain.com[:williwutzmann] |Comma-separated list of CC-receiver(s). An optional name can be added using a colon (:) | | -+------------------------------------------------------------+----------------------------------------------------------------------------------------------+------------+ -|bcc1@domain.com[:georgewutzmann] |Comma-separated list of BCC-receiver(s). An optional name can be added using a colon (:) | | -+------------------------------------------------------------+----------------------------------------------------------------------------------------------+------------+ -|replyto@domain.com[:Support-Desk] |Reply-to address. An optional name can be added using a colon (:) | | -+------------------------------------------------------------+----------------------------------------------------------------------------------------------+------------+ -|format |Flag indicating if this is a plaintext or html message. Possible values are 'plain' and 'html'| | -+------------------------------------------------------------+----------------------------------------------------------------------------------------------+------------+ -|body |Message (plain text or html) | | -+------------------------------------------------------------+----------------------------------------------------------------------------------------------+------------+ +This will send an email with subject *Latest News* from company@example.com to customer1, customer2 and customer3 by +using a realname for customer2 and customer3 and suppress generating of OoO answer if any receiver is on vacation. +Additional the CEO as well as backup will receive the mail via CC and BCC. Column: _img diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php index a909769ef85372efbc12bc94955b9f9ac1d81c26..cf36a57194b7861165a0c196db5f7d1c7f112336 100644 --- a/extension/qfq/qfq/AbstractBuildForm.php +++ b/extension/qfq/qfq/AbstractBuildForm.php @@ -380,8 +380,8 @@ abstract class AbstractBuildForm { } // Get default value - $value = ($formElement['value'] === '') ? $this->store->getVar($formElement['name'], $storeUse, - $formElement['checkType']) : $formElement['value']; + $value = ($formElement[FE_VALUE] === '') ? $this->store->getVar($formElement['name'], $storeUse, + $formElement['checkType']) : $formElement[FE_VALUE]; // Typically: $htmlElementNameIdZero = true // After Saving a record, staying on the form, the FormElements on the Client are still known as '<feName>:0'. diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php index 232b5eff804499e8b9c03f3790d9c7d46a36ee3f..68821394b7a24f7f1649a73b004e915988a54d12 100644 --- a/extension/qfq/qfq/Constants.php +++ b/extension/qfq/qfq/Constants.php @@ -151,7 +151,8 @@ const ERROR_RECORD_NOT_FOUND = 1066; const ERROR_INVALID_EDITOR_PROPERTY_NAME = 1067; const ERROR_UNKNOWN_ESCAPE_MODE = 1068; const ERROR_MISSING_CONFIG_INI_VALUE = 1069; - +const ERROR_SENDMAIL = 1070; +const ERROR_SENDMAIL_MISSING_VALUE = 1071; // Subrecord const ERROR_SUBRECORD_MISSING_COLUMN_ID = 1100; @@ -450,6 +451,7 @@ const FE_MODE = 'mode'; const FE_MODE_SQL = 'modeSql'; // TODO: Konstante FE_DYNAMIC_UPDATE ueberall einsetzen const FE_DYNAMIC_UPDATE = 'dynamicUpdate'; +const FE_VALUE = 'value'; // FormElement columns: via parameter field const FE_DATE_FORMAT = 'dateFormat'; // value: FORMAT_DATE_INTERNATIONAL | FORMAT_DATE_GERMAN @@ -465,9 +467,20 @@ const FE_SQL_UPDATE = 'sqlUpdate'; // Action: Update Statement for slave record const FE_SQL_INSERT = 'sqlInsert'; // Action: Insert Statement to create slave record. const FE_SQL_DELETE = 'sqlDelete'; // Action: Delete Statement to delete unused slave record. const FE_EDITOR_PREFIX = 'editor-'; // TinyMCE configuration settings. +const FE_SENDMAIL_TO = 'sendMailTo'; // Receiver email adresses. Separate multiple by comma. +const FE_SENDMAIL_CC = 'sendMailCc'; // CC Receiver email adresses. Separate multiple by comma. +const FE_SENDMAIL_BCC = 'sendMailBcc'; // BCC Receiver email adresses. Separate multiple by comma. +const FE_SENDMAIL_FROM = 'sendMailFrom'; // Sender email address. +const FE_SENDMAIL_SUBJECT = 'sendMailSubject'; // Email subject +const FE_SENDMAIL_REPLY_TO = 'sendMailReplyTo'; // Reply to email address +const FE_SENDMAIL_FLAG_AUTO_SUBMIT = 'sendMailFlagAutoSubmit'; // on|off - if 'on', suppresses OoO answers from receivers. +const FE_SENDMAIL_GR_ID = 'sendMailGrId'; // gr_id: used to classify mail log entries ind table mailLog +const FE_SENDMAIL_X_ID = 'sendMailXId'; // x_id: used to classify mail log entries ind table mailLog + // FormElement Types const FE_TYPE_EXTRA = 'extra'; +const FE_TYPE_SENDMAIL = 'sendMail'; const FE_TYPE_BEFORE_LOAD = 'beforeLoad'; const FE_TYPE_BEFORE_SAVE = 'beforeSave'; const FE_TYPE_BEFORE_INSERT = 'beforeInsert'; @@ -537,3 +550,16 @@ const COLUMN_PATH_FILE_NAME = 'pathFileName'; // Used to in SIP Store to handle 'delete' after upload const EXISTING_PATH_FILE_NAME = '_existingPathFileName'; + +//SENDMAIL +const SENDMAIL_IDX_RECEIVER = 0; +const SENDMAIL_IDX_SENDER = 1; +const SENDMAIL_IDX_SUBJECT = 2; +const SENDMAIL_IDX_BODY = 3; +const SENDMAIL_IDX_REPLY_TO = 4; +const SENDMAIL_IDX_FLAG_AUTO_SUBMIT = 5; +const SENDMAIL_IDX_GR_ID = 6; +const SENDMAIL_IDX_X_ID = 7; +const SENDMAIL_IDX_RECEIVER_CC = 8; +const SENDMAIL_IDX_RECEIVER_BCC = 9; +const SENDMAIL_IDX_SRC = 10; diff --git a/extension/qfq/qfq/QuickFormQuery.php b/extension/qfq/qfq/QuickFormQuery.php index ff69ea8c3522239b61559b11c02a8566f751c0c4..7ff260e52287b1a11e7daa7786226e2cf8f7e865 100644 --- a/extension/qfq/qfq/QuickFormQuery.php +++ b/extension/qfq/qfq/QuickFormQuery.php @@ -262,6 +262,7 @@ class QuickFormQuery { case FORM_SAVE: $recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP); + // Action: Before $formAction->elements($recordId, $this->feSpecAction, FE_TYPE_BEFORE_INSERT . ',' . FE_TYPE_BEFORE_UPDATE . ',' . FE_TYPE_BEFORE_SAVE); // If an old record exist: load it. Necessary to delete uploaded files which should be overwritten. @@ -275,6 +276,7 @@ class QuickFormQuery { $save->processAllUploads($rc); + // Action: After $formAction->elements($recordId, $this->feSpecAction, FE_TYPE_AFTER_INSERT . ',' . FE_TYPE_AFTER_UPDATE . ',' . FE_TYPE_AFTER_SAVE); $htmlElementNameIdZero = false; @@ -286,6 +288,9 @@ class QuickFormQuery { $htmlElementNameIdZero = true; } + // Action: Sendmail + $formAction->elements($recordId, $this->feSpecAction, FE_TYPE_SENDMAIL); + // Retrieve FE Values as JSON $data = $build->process($mode, $htmlElementNameIdZero); break; diff --git a/extension/qfq/qfq/form/FormAction.php b/extension/qfq/qfq/form/FormAction.php index ef9b75ba757a58ba064b5eed044de42ddfc79647..8da84e28879624c1c763e0ef5b42e9c467e197e1 100644 --- a/extension/qfq/qfq/form/FormAction.php +++ b/extension/qfq/qfq/form/FormAction.php @@ -12,6 +12,7 @@ require_once(__DIR__ . '/../Constants.php'); require_once(__DIR__ . '/../Database.php'); require_once(__DIR__ . '/../store/Store.php'); require_once(__DIR__ . '/../Evaluate.php'); +require_once(__DIR__ . '/../report/Sendmail.php'); /** * Class formAction @@ -70,6 +71,7 @@ class FormAction { $fe = $this->initActionFormElement($fe); + // Only process FE elements of types listed in $feTypeList. Skip all other if (false === Support::findInSet($fe[FE_TYPE], $feTypeList)) { continue; } @@ -83,6 +85,11 @@ class FormAction { continue; } + if ($fe[FE_TYPE] === FE_TYPE_SENDMAIL) { + $this->sendMail($fe); + //no further processing of current element necessary. + continue; + } // Preparation for Log, Debug $this->store->setVar(SYSTEM_FORM_ELEMENT, Logger::formatFormElementName($fe), STORE_SYSTEM); @@ -93,16 +100,21 @@ class FormAction { } /** - * Set all necessary keys + * Set all necessary keys - subsequent 'isset()' are not necessary anymore. * * @param array $fe * @return array */ private function initActionFormElement(array $fe) { - $list = [FE_TYPE, FE_SLAVE_ID, FE_SQL_VALIDATE, FE_SQL_INSERT, FE_SQL_UPDATE, FE_SQL_DELETE, FE_EXPECT_RECORDS, FE_REQUIRED_LIST, FE_MESSAGE_FAIL]; + + $list = [FE_TYPE, FE_SLAVE_ID, FE_SQL_VALIDATE, FE_SQL_INSERT, FE_SQL_UPDATE, FE_SQL_DELETE, FE_EXPECT_RECORDS, + FE_REQUIRED_LIST, FE_MESSAGE_FAIL, FE_SENDMAIL_TO, FE_SENDMAIL_CC, FE_SENDMAIL_BCC, FE_SENDMAIL_FROM, FE_SENDMAIL_SUBJECT, FE_SENDMAIL_REPLY_TO, + FE_SENDMAIL_FLAG_AUTO_SUBMIT, FE_SENDMAIL_GR_ID, FE_SENDMAIL_X_ID]; + foreach ($list as $key) { Support::setIfNotSet($fe, $key); } + return $fe; } @@ -152,6 +164,27 @@ class FormAction { return true; } + /** + * @param array $feSpecAction + */ + private function sendMail(array $feSpecAction) { + + $mail[SENDMAIL_IDX_RECEIVER] = $this->evaluate->parse($feSpecAction[FE_SENDMAIL_TO]); + $mail[SENDMAIL_IDX_SENDER] = $this->evaluate->parse($feSpecAction[FE_SENDMAIL_FROM]); + $mail[SENDMAIL_IDX_SUBJECT] = $this->evaluate->parse($feSpecAction[FE_SENDMAIL_SUBJECT]); + $mail[SENDMAIL_IDX_BODY] = $this->evaluate->parse($feSpecAction[FE_VALUE]); + $mail[SENDMAIL_IDX_REPLY_TO] = $this->evaluate->parse($feSpecAction[FE_SENDMAIL_REPLY_TO]); + $mail[SENDMAIL_IDX_FLAG_AUTO_SUBMIT] = $this->evaluate->parse($feSpecAction[FE_SENDMAIL_FLAG_AUTO_SUBMIT]) === 'on' ? 'on' : 'off'; + $mail[SENDMAIL_IDX_GR_ID] = $this->evaluate->parse($feSpecAction[FE_SENDMAIL_GR_ID]); + $mail[SENDMAIL_IDX_X_ID] = $this->evaluate->parse($feSpecAction[FE_SENDMAIL_X_ID]); + $mail[SENDMAIL_IDX_RECEIVER_CC] = $this->evaluate->parse($feSpecAction[FE_SENDMAIL_CC]); + $mail[SENDMAIL_IDX_RECEIVER_BCC] = $this->evaluate->parse($feSpecAction[FE_SENDMAIL_BCC]); + $mail[SENDMAIL_IDX_SRC] = "FormId: " . $feSpecAction['formId'] . ", FormElementId: " . $feSpecAction['id']; + + // Mail: send + new Sendmail($mail); + } + /** * If there is a query defined in fe.parameter.FE_SQL_VALIDATE: fire them. * Count the selected records and compare them with fe.parameter.FE_EXPECT_RECORDS. diff --git a/extension/qfq/qfq/report/Report.php b/extension/qfq/qfq/report/Report.php index 48891401fc601ac852470091bb75a57908a1c4d6..b8dcb4e7bb7bb31141a8415baf17ffacc4b6e3cc 100644 --- a/extension/qfq/qfq/report/Report.php +++ b/extension/qfq/qfq/report/Report.php @@ -46,10 +46,6 @@ class Report { * @var string */ private $dbAlias = ''; - /** - * @var Log - */ - private $log = null; // frArray[10.50.5.sql][select ...] private $frArray = array(); @@ -77,11 +73,6 @@ class Report { */ private $db = null; - /** - * @var Sendmail - */ - private $sendmail = null; - /** * @var array */ @@ -145,12 +136,6 @@ class Report { // Merged URL-Parameter (key1, id etc...) in resultArray. $this->variables->resultArray = array_merge($this->variables->resultArray, array("global." => $this->variables->collectGlobalVariables())); - // Create Logclass. - $this->log = new Log($this->variables->resultArray['global.']); - - // Create sendmail Class. Take care to prepare a fr_log instance. - $this->sendmail = new Sendmail($this->log); - } /** @@ -165,8 +150,6 @@ class Report { $this->indexArray = array(); $this->levelCount = 0; - $this->log->set_fr_error($this->fr_error); - // Iteration over Bodytext $ttLineArray = explode("\n", $bodyText); @@ -189,6 +172,7 @@ class Report { * Example: 10.50.5.sql = select * from person * * @param string $ttLine : line to split in level, command, content + * @throws SyntaxReportException * @return void */ private function parseFRLine($ttLine) { @@ -647,32 +631,32 @@ class Report { if (empty($columnValue)) break; - $tmp = explode("|", $columnValue, 3); + $mailarr = explode("|", $columnValue, 3); // Fake values for tmp[1], tmp[2] to suppress access errors. - $tmp[] = ''; - $tmp[] = ''; + $mailarr[] = ''; + $mailarr[] = ''; - if (empty($tmp[0])) + if (empty($mailarr[0])) break; - $attribute = Support::doAttribute('src', $tmp[0]); - $attribute .= Support::doAttribute('alt', $tmp[1]); + $attribute = Support::doAttribute('src', $mailarr[0]); + $attribute .= Support::doAttribute('alt', $mailarr[1]); - $content .= '<img ' . $attribute . '>' . $tmp[2]; + $content .= '<img ' . $attribute . '>' . $mailarr[2]; break; case "mailto": // "<email address>|[Real Name]" renders to (encrypted via JS): <a href="mailto://<email address>"><email address></a> OR <a href="mailto://<email address>">[Real Name]</a> - $tmp = explode("|", $columnValue, 2); - if (empty($tmp[0])) + $mailarr = explode("|", $columnValue, 2); + if (empty($mailarr[0])) break; - $t1 = explode("@", $tmp[0], 2); + $t1 = explode("@", $mailarr[0], 2); $content .= "<script language=javascript><!--" . chr(10); - if (empty($tmp[1])) $tmp[1] = $tmp[0]; + if (empty($mailarr[1])) $mailarr[1] = $mailarr[0]; - $content .= 'var contact = "' . substr($tmp[1], 0, 2) . '"' . chr(10); - $content .= 'var contact1 = "' . substr($tmp[1], 2) . '"' . chr(10); + $content .= 'var contact = "' . substr($mailarr[1], 0, 2) . '"' . chr(10); + $content .= 'var contact1 = "' . substr($mailarr[1], 2) . '"' . chr(10); $content .= 'var email = "' . $t1[0] . '"' . chr(10); $content .= 'var emailHost = "' . $t1[1] . '"' . chr(10); @@ -682,18 +666,35 @@ class Report { break; case "sendmail": - // 'Absender|Empfaenger, mehrere mit Komma getrennt|Betreff|Mailinhalt' - $tmp = explode("|", $columnValue, 4); - if (count($tmp) < 4) { + // '<receiver1>,<receiver2>,...|<sender>|<subject>|<body>|<reply-to>|<flag autosubmit: on /off>' + $mailarr = explode("|", $columnValue); + if (count($mailarr) < 4) { throw new SyntaxReportException ("Too few parameter for sendmail: $columnValue", ERROR_TOO_FEW_PARAMETER_FOR_SENDMAIL, null, __FILE__, __LINE__, $this->fr_error); } - $mail['receiver'] = $tmp[0]; - $mail['sender'] = $tmp[1]; - $mail['subject'] = $tmp[2]; - $mail['body'] = $tmp[3]; + if (!isset($mailarr[SENDMAIL_IDX_REPLY_TO])) + $mailarr[SENDMAIL_IDX_REPLY_TO] = ''; + + if (!isset($mailarr[SENDMAIL_IDX_FLAG_AUTO_SUBMIT])) + $mailarr[SENDMAIL_IDX_FLAG_AUTO_SUBMIT] = 'off'; + + if (!isset($mailarr[SENDMAIL_IDX_GR_ID])) + $mailarr[SENDMAIL_IDX_GR_ID] = '0'; + + if (!isset($mailarr[SENDMAIL_IDX_X_ID])) + $mailarr[SENDMAIL_IDX_X_ID] = '0'; + + if (!isset($mailarr[SENDMAIL_IDX_RECEIVER_CC])) + $mailarr[SENDMAIL_IDX_RECEIVER_CC] = ''; + + if (!isset($mailarr[SENDMAIL_IDX_RECEIVER_BCC])) + $mailarr[SENDMAIL_IDX_RECEIVER_BCC] = ''; + + $mailarr[SENDMAIL_IDX_SRC] = "Report: T3 pageId=" . $this->store->getVar('pageId', STORE_TYPO3) . + ", T3 ttcontentId=" . $this->store->getVar('ttcontentUid', STORE_TYPO3) . + ", Level=" . $full_level; - $content = $this->sendmail->sendmail($mail); + new Sendmail($mailarr); break; case "vertical": @@ -705,11 +706,11 @@ class Report { # width $width = $arr[2] ? $arr[2] : "1em"; - $tmp = "width:$width; "; + $mailarr = "width:$width; "; # height if ($arr[3]) - $tmp .= "height:" . $arr[3] . "; "; + $mailarr .= "height:" . $arr[3] . "; "; # tag if ($arr[4]) { diff --git a/extension/qfq/qfq/report/Sendmail.php b/extension/qfq/qfq/report/Sendmail.php index 7780b90bd394c0c5b9b23eb5a46bcd8a920d122d..02706543f66a580a9885992c610503c6bfa6b8d8 100644 --- a/extension/qfq/qfq/report/Sendmail.php +++ b/extension/qfq/qfq/report/Sendmail.php @@ -4,57 +4,102 @@ namespace qfq; //use qfq; -require_once(__DIR__ . '/Define.php'); -require_once(__DIR__ . '/Error.php'); - +require_once(__DIR__ . '/../Constants.php'); +require_once(__DIR__ . '/../Database.php'); class Sendmail { /** - * @var Log + * Sends a mail as specified in $mailarr. + * If there is no receiver specified as 'TO': no mail is sent. This is ok and no error. + * Logs every send mail as a record in table `mailLog`. Additionally a `grId` and a `xId` can be specified + * to assing the logentry to a specific action. + * The log record also contains some information which generates the mail (form/formelement or QFQ query). + * + * Structure mailarr: + * SENDMAIL_IDX_RECEIVER email address(es) + * SENDMAIL_IDX_SENDER email address + * SENDMAIL_IDX_SUBJECT string + * SENDMAIL_IDX_BODY string + * SENDMAIL_IDX_REPLY_TO optional: email address + * SENDMAIL_IDX_FLAG_AUTO_SUBMIT optional: 'on'|'off' + * SENDMAIL_IDX_GR_ID optional: integer + * SENDMAIL_IDX_X_ID optional: integer + * + * @param $mailarr + * @throws UserFormException */ - private $Log; + public function __construct(array $mailarr) { + + // If there is no 'Receiver': do not send a mail. + if (!isset($mailarr[SENDMAIL_IDX_RECEIVER]) || $mailarr[SENDMAIL_IDX_RECEIVER] === '') { + return; + } + + if (count($mailarr) < 4 || $mailarr[SENDMAIL_IDX_SENDER] === '' || $mailarr[SENDMAIL_IDX_SUBJECT] === '' || $mailarr[SENDMAIL_IDX_BODY] === '') { + throw new UserFormException("Error sendmail missing one of: receiver, sender, subject or body", ERROR_SENDMAIL_MISSING_VALUE); + } + + $header = $this->buildHeader($mailarr); + if (!(mb_send_mail($mailarr[SENDMAIL_IDX_RECEIVER], $mailarr[SENDMAIL_IDX_SUBJECT], $mailarr[SENDMAIL_IDX_BODY], $header, "-f " . $mailarr[SENDMAIL_IDX_SENDER]))) { + throw new UserFormException("Error sendmail failed.", ERROR_SENDMAIL); + } + + $this->mailLog($mailarr, $header); + } /** - * Constructor: - * - * @param Log $fr_log + * @param $mailarr + * @return string */ + private function buildHeader($mailarr) { + + // "\r\n" needs to be enclosed in double ticks to correctly converted to 0x0d 0x0a, + $header = "From: " . $mailarr[SENDMAIL_IDX_SENDER] . "\r\n"; + + if (isset($mailarr[SENDMAIL_IDX_REPLY_TO]) && $mailarr[SENDMAIL_IDX_REPLY_TO] != '') { + $header .= "Reply-To: " . $mailarr[SENDMAIL_IDX_REPLY_TO] . "\r\n"; + } + + if (isset($mailarr[SENDMAIL_IDX_FLAG_AUTO_SUBMIT]) && $mailarr[SENDMAIL_IDX_FLAG_AUTO_SUBMIT] === 'on') { + $header .= "Auto-Submitted: auto-send\r\n"; + } - public function __construct(Log $fr_log) { + if (isset($mailarr[SENDMAIL_IDX_RECEIVER_CC]) && $mailarr[SENDMAIL_IDX_RECEIVER_CC] != '') { + $header .= "Cc: " . $mailarr[SENDMAIL_IDX_RECEIVER_CC] . "\r\n"; + } + + if (isset($mailarr[SENDMAIL_IDX_RECEIVER_BCC]) && $mailarr[SENDMAIL_IDX_RECEIVER_BCC] != '') { + $header .= "Bcc: " . $mailarr[SENDMAIL_IDX_RECEIVER_BCC] . "\r\n"; + } - $this->Log = $fr_log; + return $header; } /** - * Send an email. Mail delivery should work - else the mails might disappear - * Seperate lines in the body with '\r\n' - * RC: if RC==0 Returns Output, else 'RC - Output' + * Creates a new MailLog Record based on $mailArr / $header. * - * @param array $mailarr : $mailarr['receiver'] (multiple with comma), $mailarr['sender'], $mailarr['subject'], $mailarr['body'] - * @return string + * @param array $mailarr + * @param $headers + * @throws CodeException + * @throws DbException */ + private function mailLog(array $mailarr, $header) { - public function sendmail($mailarr) { - $status = 'E'; - - // sending only if there is a receiver ! - if ($mailarr['receiver']) { - // if(mail($receiver,$subject,$message, "From: ".$sender."\nX-Mailer: PHP/ . $phpversion()", "-f ".$sender)) - if (mail($mailarr['receiver'], $mailarr['subject'], $mailarr['body'], "X-Mailer: PHP/" . phpversion() . "\r\nFrom: " . $mailarr['sender'] . ".\r\n", "-f " . $mailarr['sender'])) { - $msg = "Mail has been sent"; - $status = 'I'; - } else { - $msg = "Sending Mail not accepted"; - } - } else { - $msg = "Mail not sent: missing receiver"; - } + $log = array(); - // Log every mail - $this->Log->log_mail("form", $status, $msg, $mailarr); + // Log + $log[SENDMAIL_IDX_RECEIVER] = $mailarr[SENDMAIL_IDX_RECEIVER]; + $log[SENDMAIL_IDX_SENDER] = $mailarr[SENDMAIL_IDX_SENDER]; + $log[SENDMAIL_IDX_SUBJECT] = $mailarr[SENDMAIL_IDX_SUBJECT]; + $log[SENDMAIL_IDX_BODY] = $mailarr[SENDMAIL_IDX_BODY]; + $log[4] = $header; + $log[5] = $mailarr[SENDMAIL_IDX_GR_ID]; + $log[6] = $mailarr[SENDMAIL_IDX_X_ID]; + $log[7] = $mailarr[SENDMAIL_IDX_SRC]; - return ($msg); - } // sendmail() + $db = new Database(); + $db->sql('INSERT INTO MailLog (`receiver`, `sender`, `subject`, `body`, `header`, `grId`, `xId`, `src`) VALUES ( ?, ? ,?, ?, ? ,?, ?, ? )', ROW_REGULAR, $log); + } } diff --git a/extension/qfq/sql/formEditor.sql b/extension/qfq/sql/formEditor.sql index e0ed256dc3b3853d214eb6b660ad2f9022013249..22ccc0e5eed3aa0725ea078145493b8c24d7fc4d 100644 --- a/extension/qfq/sql/formEditor.sql +++ b/extension/qfq/sql/formEditor.sql @@ -38,6 +38,7 @@ CREATE TABLE IF NOT EXISTS `Form` ( DEFAULT CHARSET = utf8 AUTO_INCREMENT = 0; + #-- #-- Triggers `Form` #-- @@ -70,7 +71,7 @@ CREATE TABLE IF NOT EXISTS `FormElement` ( `type` ENUM('checkbox', 'date', 'datetime', 'dateJQW', 'datetimeJQW', 'extra', 'gridJQW', 'text', 'editor', 'time', 'note', 'password', 'radio', 'select', 'subrecord', 'upload', 'fieldset', 'pill', 'beforeLoad', 'beforeSave', 'beforeInsert', 'beforeUpdate', 'beforeDelete', 'afterLoad', - 'afterSave', 'afterInsert', 'afterUpdate', 'afterDelete', 'sendmail') NOT NULL DEFAULT 'text', + 'afterSave', 'afterInsert', 'afterUpdate', 'afterDelete', 'sendMail') NOT NULL DEFAULT 'text', `subrecordOption` SET('edit', 'delete', 'new') NOT NULL DEFAULT '', `checkType` ENUM('alnumx', 'digit', 'email', 'min|max', 'min|max date', 'pattern', 'allbut', 'all') NOT NULL DEFAULT 'alnumx', `checkPattern` VARCHAR(255) NOT NULL DEFAULT '', @@ -208,7 +209,7 @@ VALUES (2, 'modeSql', 'Mode sql', 'show', 'text', 'all', 'native', 170, '70,2', 255, '', '', '', '', '', '', 100, '', 'no', '', '', '', ''), (2, 'class', 'Class', 'show', 'select', 'all', 'native', 180, 0, 255, '', '', '{{class:FSRD0:alnumx}}', '', '', '', 100, '', 'yes', '', '', '', ''), (2, 'type', 'Type', 'show', 'select', 'all', 'native', 190, 0, 255, '', '', '', '', '', - 'itemList={{SELECT IF( "{{class:FRD0:alnumx}}"="native","checkbox,date,time,datetime,dateJQW,datetimeJQW,extra,gridJQW,text,editor,note,password,radio,select,subrecord,upload", IF("{{class:FRD0:alnumx}}"="action","beforeLoad,beforeSave,beforeInsert,beforeUpdate,beforeDelete,afterLoad,afterSave,afterInsert,afterUpdate,afterDelete,sendmail", "fieldset,pill") ) }}', + 'itemList={{SELECT IF( "{{class:FRD0:alnumx}}"="native","checkbox,date,time,datetime,dateJQW,datetimeJQW,extra,gridJQW,text,editor,note,password,radio,select,subrecord,upload", IF("{{class:FRD0:alnumx}}"="action","beforeLoad,beforeSave,beforeInsert,beforeUpdate,beforeDelete,afterLoad,afterSave,afterInsert,afterUpdate,afterDelete,sendMail", "fieldset,pill") ) }}', 100, '', 'yes', '', '', '', ''), (2, 'subrecordOption', 'Subrecord Option', 'show', 'checkbox', 'all', 'native', 200, 0, 0, '', '', '', '', '', '', 100, '', 'no', '', '', '', ''), @@ -227,8 +228,8 @@ VALUES (2, 'note', 'note', 'show', 'text', 'all', 'native', 450, 0, 255, '', '', '', '', '', '', 102, '', 'no', '', '', '', ''), (2, 'tooltip', 'Tooltip', 'show', 'text', 'all', 'native', 460, 0, 255, '', '', '', '', '', '', 102, '', 'no', '', '', '', ''), (2, 'placeholder', 'Placeholder', 'show', 'text', 'all', 'native', 470, 0, 255, '', '', '', '', '', '', 102, '', 'no', '', '', '', ''), - (2, 'value', 'value', 'show', 'text', 'all', 'native', 500, 0, 255, '', '', '', '', '', '', 103, '', 'no', '', '', '', ''), - (2, 'sql1', 'sql1', 'show', 'text', 'all', 'native', 510, '70,5', 255, '', '', '', '', '', '', 103, '', 'no', '', '', '', ''), + (2, 'value', 'value', 'show', 'text', 'all', 'native', 500, '40,2', 255, '', '', '', '', '', '', 103, '', 'no', '', '', '', ''), + (2, 'sql1', 'sql1', 'show', 'text', 'all', 'native', 510, '40,5', 255, '', '', '', '', '', '', 103, '', 'no', '', '', '', ''), (2, 'parameter', 'Parameter', 'show', 'text', 'all', 'native', 520, '40,4', 255, '', '', '', '', '', '', 103, '', 'no', '', '', '', ''), (2, 'clientJs', 'ClientJS', 'show', 'text', 'all', 'native', 530, 0, 255, '', '', '', '', '', '', 103, '', 'no', '', '', '', ''), @@ -239,3 +240,39 @@ VALUES (2, 'created', 'Created', 'readonly', 'text', 'all', 'native', 630, 0, 20, '', '', '', '', '', '', 104, '', 'no', '', '', '', ''); + +# ---------------------------------------- +# MailLog + +DROP TABLE IF EXISTS `MailLog`; +CREATE TABLE `MailLog` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `grId` INT(11) NOT NULL DEFAULT '0', + `xId` INT(11) NOT NULL DEFAULT '0', + `receiver` TEXT NOT NULL DEFAULT '', + `sender` VARCHAR(255) NOT NULL DEFAULT '', + `subject` VARCHAR(255) NOT NULL DEFAULT '', + `body` TEXT NOT NULL DEFAULT '', + `header` VARCHAR(255) NOT NULL DEFAULT '', + `attach` VARCHAR(255) NOT NULL DEFAULT '', + `src` VARCHAR(255) NOT NULL DEFAULT '', + `modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + + PRIMARY KEY (`id`) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8 + AUTO_INCREMENT = 0; + + +#-- +#-- Triggers `MailLog` +#-- +#DROP TRIGGER IF EXISTS `on_MailLog_update_modified`; +#DELIMITER // +#CREATE TRIGGER `on_MailLog_update_modified` BEFORE UPDATE ON `MailLog` +#FOR EACH ROW SET NEW.modified = +#current_timestamp() +#// +#DELIMITER ;