Update existing ticket in VTiger - php
I am a newbie to VTiger, I am using the 5.2.0 version to try, learn implementing Issue Tracking.
Intro:
A client sends an email to say support#company.com, Mail Converter or Mail Scanner.. scans for the new email and if found creates a new ticket.
If admin sees a new ticket which is being raised in Trouble Tickets, makes some changes such as assigning it to someone, or making a comment etc.. VTiger CRM sends an email to a client saying that admin has made modifications to the ticket.
Lets say Client wants some changes, so he replies to support#company.com, a new ticket is raised because a new mail as arrived and mail scanner creates a new ticket.
Problem:
Instead of updating an existing ticket which the client has sent before, creating a new ticket everytime duplicates the problem by making many tickets for one issue, which is a big problem.
When ever a client sends a mail to support#company.com, Subject of email goes as Title of the Ticket and Body of Email as Description of Ticket.
Lets say
Title of Ticket is SubjectClientSent
Client didnot like something after admin makes some modifications and the client decides to reply to the email which VTiger has sent him, it is generally in this manner.
Re: TT17 [ Ticket Id : 22 ] Re : SubjectClientSent
I dont want Mail Scanner to create a new ticket with the title of ticket as Re: TT17 [ Ticket Id : 22 ] Re : SubjectClientSent , I want it to update the exiting ticket with title SubjectClientSent
I tried to do that with creating a new rule something like this..
But, its still creating a new ticket.
Could you help me correct this?
Is there a better way of updating the existing ticket?
Thanks for the help and support.
Found the solution!
The entire answer was written stealing information from the VTiger PDF document, VTiger Forum, VTiger Bug Link
The below pictures shows the basic process involved in automating ticketing with MailScanner or MailConverter
![Mail Scanner Basic Process][4]
1:
Customer (having a Contact/Account record) sends email to support#company.com, with subject
“Test Trouble Ticket”
2:
Mail Scanner creates ticket, links it to matching contact/account record filtered by emailid
lookup.
HelpDeskHandler will send a acknowledgment email with more information on how to respond
further to Customer. The email subject looks like “TT15 [Ticket Id: 1483] Test Trouble Ticket”
3:
Customer replies to the acknowledgment email keeping part of the subject intact to
support#company.com. As mail scanner is configured with Regex rule on subject and finds a
matching Trouble Ticket linked to Customer, it updates the comments with the email body.
4:
When support team update their comment, an email is sent to Customer again.
The following steps will help us achieve this functionality
Step 1: Setup Outgoing Mail Server
If your Outgoing Mail Server is Gmail, the following settings should work for you
Mail Server Settings (SMTP)
Server Name ssl://smtp.gmail.com:465
User Name username#gmail.com
Password ******
From Email from.email#gmail.com
Requires Authentication? Yes
Step 2: Setup MailScanner or MailConverter
DEFAULT Information
Scanner Name DEFAULT
Server Name imap.gmail.com
Protocol imap4
User Name support.company#gmail.com
SSL Type ssl
SSL Method novalidate-cert
Connect URL {imap.gmail.com:993/imap4/ssl/novalidate-cert}
Status Enabled
Scanning Information
Look for All Messages from lastscan
After scan Mark message as Read
Step 3: Setup Rules to create & update tickets in MailScanner or MailConverter
Rules For Mail Converter [DEFAULT]
Priority
From
To
Subject Regex Ticket Id[^:]?: ([0-9]+)
Body
Match All Condition
Action Update Ticket
Priority
From
To
Subject
Body
Match Any Condition
Action Create Ticket
Step 4: Configure config.inc.php
update the following variables in your config.inc.php
$HELPDESK_SUPPORT_EMAIL_ID
FROM address information to be used when sending mails
Example: automated-reply#company.com
$HELPDESK_SUPPORT_EMAIL_ID = 'auto.reply.company#gmail.com';
$HELPDESK_SUPPORT_NAME
FROM name to be used for purpose of display for emails sentout.
Example: Automated Reply
$HELPDESK_SUPPORT_NAME = 'Company Support';
$HELPDESK_SUPPORT_EMAIL_REPLY_ID
REPLY-TO address to be set in the email sent.
Example: support#company.com
$HELPDESK_SUPPORT_EMAIL_REPLY_ID = 'support.company#gmail.com';
Setting this information is one of the important step for autoticketing.
When user tries to Reply for the automated emails the TO
address will be set by the mail-client and reaches the MailBox for
which we have setup the scanning.
Step 5: Create HelpDeskHandler.php in VTigerCRM/modules/HelpDesk/
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
class HelpDeskHandler extends VTEventHandler {
function __getSendToEmail($crmid) {
if(empty($crmid)) return false;
$sendtoemail = false;
global $adb;
$metaresult = $adb->pquery("SELECT setype FROM vtiger_crmentity WHERE crmid=? AND deleted = 0", array($crmid));
if($metaresult && $adb->num_rows($metaresult)) {
$metaresultrow = $adb->fetch_array($metaresult);
$emailres = false;
if($metaresultrow['setype'] == 'Contacts') {
$emailres = $adb->pquery("SELECT email,yahooid FROM vtiger_contactdetails WHERE contactid = ?", array($crmid));
} else if($metaresultrow['setype'] == 'Accounts') {
$emailres = $adb->pquery("SELECT email1,email2 FROM vtiger_account WHERE accountid = ?", array($crmid));
}
if($emailres && $adb->num_rows($emailres)) {
$emailresrow = $adb->fetch_array($emailres);
if(!empty($emailresrow[0])) $sendtoemail = $emailresrow[0];
if(!empty($emailresrow[1])) $sendtoemail = $emailresrow[1];
}
}
return $sendtoemail;
}
function handleEvent($eventName, $entityData) {
global $log, $adb;
if($eventName == 'vtiger.entity.aftersave') {
$moduleName = $entityData->getModuleName();
// Event not related to HelpDesk - IGNORE
if($moduleName != 'HelpDesk') {
return;
}
// Take action if the service running is MailScanner (either via Cron/Scan Now)
if(isset($_REQUEST) && $_REQUEST['service'] == 'MailScanner' ) {
$focus = $entityData->focus;
$sendToEmail = $this->__getSendToEmail($focus->column_fields['parent_id']);
// If the entity is create new and we know whom to send the mail proceed.
if($entityData->isNew() && $sendToEmail) {
global $HELPDESK_SUPPORT_EMAIL_ID, $HELPDESK_SUPPORT_NAME, $HELPDESK_SUPPORT_EMAIL_REPLY_ID;
include_once 'vtlib/Vtiger/Mailer.php';
$mailer = new Vtiger_Mailer();
$mailer->ConfigSenderInfo($HELPDESK_SUPPORT_EMAIL_ID, $HELPDESK_SUPPORT_NAME);
$mailer->AddReplyTo($HELPDESK_SUPPORT_EMAIL_REPLY_ID);
$mailer->initFromTemplate('Auto Ticket First Response Template');
// Update the email subject
$mailer->Subject = sprintf("%s [ Ticket Id : %s ] Re : %s",
$focus->column_fields['ticket_no'],
$focus->id,
$focus->column_fields['ticket_title']
);
$mailer->SendTo( $sendToEmail, '', false, false, true );
}
}
}
}
}
?>
Step 6: Create email template named as "Auto Ticket First Response"
This is an acknowledgement email Company Support automatically sends after client sends email to support.company#gmail.com
To create Email Template go to Settings/E-Mail Templates; Select New Template and name it as "Auto Ticket First Response"
Step 7: Create a new PHP file and name it as RegisterHelpDeskHandler.php
Place the following code & execute the file
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
$Vtiger_Utils_Log = true;
include_once 'vtlib/Vtiger/Module.php';
include_once 'vtlib/Vtiger/Event.php';
$moduleInstance = Vtiger_Module::getInstance('HelpDesk');
Vtiger_Event::register($moduleInstance, 'vtiger.entity.aftersave', 'HelpDeskHandler', 'modules/HelpDesk/HelpDeskHandler.php');
?>
To execute, simply type the following URL
http://localhost:8888/registerHelpDeskHandler.php
You should see the following output in the browser
Registering Event vtiger.entity.aftersave with [modules/HelpDesk/HelpDeskHandler.php] HelpDeskHandler ... DONE
Step 9: Check for the bug!
If you are on VTiger 5.2.0, the bug is already fixed!
If not, go to modules/Settings/MailScanner/core/MailScannerAction.php and replace the entire code with the following code
<?php
/*********************************************************************************
** The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
*
********************************************************************************/
require_once('modules/Emails/Emails.php');
require_once('modules/HelpDesk/HelpDesk.php');
require_once('modules/Users/Users.php');
require_once('modules/Documents/Documents.php');
/**
* Mail Scanner Action
*/
class Vtiger_MailScannerAction {
// actionid for this instance
var $actionid = false;
// scanner to which this action is associated
var $scannerid = false;
// type of mailscanner action
var $actiontype= false;
// text representation of action
var $actiontext= false;
// target module for action
var $module = false;
// lookup information while taking action
var $lookup = false;
// Storage folder to use
var $STORAGE_FOLDER = 'storage/mailscanner/';
/** DEBUG functionality */
var $debug = false;
function log($message) {
global $log;
if($log && $this->debug) { $log->debug($message); }
else if($this->debug) echo "$message\n";
}
/**
* Constructor.
*/
function __construct($foractionid) {
$this->initialize($foractionid);
}
/**
* Initialize this instance.
*/
function initialize($foractionid) {
global $adb;
$result = $adb->pquery("SELECT * FROM vtiger_mailscanner_actions WHERE actionid=? ORDER BY sequence", Array($foractionid));
if($adb->num_rows($result)) {
$this->actionid = $adb->query_result($result, 0, 'actionid');
$this->scannerid = $adb->query_result($result, 0, 'scannerid');
$this->actiontype = $adb->query_result($result, 0, 'actiontype');
$this->module = $adb->query_result($result, 0, 'module');
$this->lookup = $adb->query_result($result, 0, 'lookup');
$this->actiontext = "$this->actiontype,$this->module,$this->lookup";
}
}
/**
* Create/Update the information of Action into database.
*/
function update($ruleid, $actiontext) {
global $adb;
$inputparts = explode(',', $actiontext);
$this->actiontype = $inputparts[0]; // LINK, CREATE
$this->module = $inputparts[1]; // Module name
$this->lookup = $inputparts[2]; // FROM, TO
$this->actiontext = $actiontext;
if($this->actionid) {
$adb->pquery("UPDATE vtiger_mailscanner_actions SET scannerid=?, actiontype=?, module=?, lookup=? WHERE actionid=?",
Array($this->scannerid, $this->actiontype, $this->module, $this->lookup, $this->actionid));
} else {
$this->sequence = $this->__nextsequence();
$adb->pquery("INSERT INTO vtiger_mailscanner_actions(scannerid, actiontype, module, lookup, sequence) VALUES(?,?,?,?,?)",
Array($this->scannerid, $this->actiontype, $this->module, $this->lookup, $this->sequence));
$this->actionid = $adb->database->Insert_ID();
}
$checkmapping = $adb->pquery("SELECT COUNT(*) AS ruleaction_count FROM vtiger_mailscanner_ruleactions
WHERE ruleid=? AND actionid=?", Array($ruleid, $this->actionid));
if($adb->num_rows($checkmapping) && !$adb->query_result($checkmapping, 0, 'ruleaction_count')) {
$adb->pquery("INSERT INTO vtiger_mailscanner_ruleactions(ruleid, actionid) VALUES(?,?)",
Array($ruleid, $this->actionid));
}
}
/**
* Delete the actions from tables.
*/
function delete() {
global $adb;
if($this->actionid) {
$adb->pquery("DELETE FROM vtiger_mailscanner_actions WHERE actionid=?", Array($this->actionid));
$adb->pquery("DELETE FROM vtiger_mailscanner_ruleactions WHERE actionid=?", Array($this->actionid));
}
}
/**
* Get next sequence of Action to use.
*/
function __nextsequence() {
global $adb;
$seqres = $adb->pquery("SELECT max(sequence) AS max_sequence FROM vtiger_mailscanner_actions", Array());
$maxsequence = 0;
if($adb->num_rows($seqres)) {
$maxsequence = $adb->query_result($seqres, 0, 'max_sequence');
}
++$maxsequence;
return $maxsequence;
}
/**
* Apply the action on the mail record.
*/
function apply($mailscanner, $mailrecord, $mailscannerrule, $matchresult) {
$returnid = false;
if($this->actiontype == 'CREATE') {
if($this->module == 'HelpDesk') {
$returnid = $this->__CreateTicket($mailscanner, $mailrecord);
}
} else if($this->actiontype == 'LINK') {
$returnid = $this->__LinkToRecord($mailscanner, $mailrecord);
} else if($this->actiontype == 'UPDATE') {
if($this->module == 'HelpDesk') {
$returnid = $this->__UpdateTicket($mailscanner, $mailrecord,
$mailscannerrule->hasRegexMatch($matchresult));
}
}
return $returnid;
}
/**
* Update ticket action.
*/
function __UpdateTicket($mailscanner, $mailrecord, $regexMatchInfo) {
global $adb;
$returnid = false;
$usesubject = false;
if($this->lookup == 'SUBJECT') {
// If regex match was performed on subject use the matched group
// to lookup the ticket record
if($regexMatchInfo) $usesubject = $regexMatchInfo['matches'];
else $usesubject = $mailrecord->_subject;
// Get the ticket record that was created by SENDER earlier
$fromemail = $mailrecord->_from[0];
$linkfocus = $mailscanner->GetTicketRecord($usesubject, $fromemail);
$relatedid = $linkfocus->column_fields[parent_id];
// If matching ticket is found, update comment, attach email
if($linkfocus) {
$timestamp = $adb->formatDate(date('YmdHis'), true);
$adb->pquery("INSERT INTO vtiger_ticketcomments(ticketid, comments, ownerid, ownertype, createdtime) VALUES(?,?,?,?,?)",
Array($linkfocus->id, $mailrecord->getBodyText(), $relatedid, 'customer', $timestamp));
// Set the ticket status to Open if its Closed
$adb->pquery("UPDATE vtiger_troubletickets set status=? WHERE ticketid=? AND status='Closed'", Array('Open', $linkfocus->id));
$returnid = $this->__CreateNewEmail($mailrecord, $this->module, $linkfocus);
} else {
// TODO If matching ticket was not found, create ticket?
// $returnid = $this->__CreateTicket($mailscanner, $mailrecord);
}
}
return $returnid;
}
/**
* Create ticket action.
*/
function __CreateTicket($mailscanner, $mailrecord) {
// Prepare data to create trouble ticket
$usetitle = $mailrecord->_subject;
$description = $mailrecord->getBodyText();
// There will be only on FROM address to email, so pick the first one
$fromemail = $mailrecord->_from[0];
$linktoid = $mailscanner->LookupContact($fromemail);
if(!$linktoid) $linktoid = $mailscanner->LookupAccount($fromemail);
/** Now Create Ticket **/
global $current_user;
if(!$current_user) $current_user = new Users();
$current_user->id = 1;
// Create trouble ticket record
$ticket = new HelpDesk();
$ticket->column_fields['ticket_title'] = $usetitle;
$ticket->column_fields['description'] = $description;
$ticket->column_fields['ticketstatus'] = 'Open';
$ticket->column_fields['assigned_user_id'] = $current_user->id;
if($linktoid) $ticket->column_fields['parent_id'] = $linktoid;
$ticket->save('HelpDesk');
// Associate any attachement of the email to ticket
$this->__SaveAttachements($mailrecord, 'HelpDesk', $ticket);
return $ticket->id;
}
/**
* Add email to CRM record like Contacts/Accounts
*/
function __LinkToRecord($mailscanner, $mailrecord) {
$linkfocus = false;
$useemail = false;
if($this->lookup == 'FROM') $useemail = $mailrecord->_from;
else if($this->lookup == 'TO') $useemail = $mailrecord->_to;
if($this->module == 'Contacts') {
foreach($useemail as $email) {
$linkfocus = $mailscanner->GetContactRecord($email);
if($linkfocus) break;
}
} else if($this->module == 'Accounts') {
foreach($useemail as $email) {
$linkfocus = $mailscanner->GetAccountRecord($email);
if($linkfocus) break;
}
}
$returnid = false;
if($linkfocus) {
$returnid = $this->__CreateNewEmail($mailrecord, $this->module, $linkfocus);
}
return $returnid;
}
/**
* Create new Email record (and link to given record) including attachements
*/
function __CreateNewEmail($mailrecord, $module, $linkfocus) {
global $current_user, $adb;
if(!$current_user) $current_user = new Users();
$current_user->id = 1;
$focus = new Emails();
$focus->column_fields['parent_type'] = $module;
$focus->column_fields['activitytype'] = 'Emails';
$focus->column_fields['parent_id'] = "$linkfocus->id#-1|";
$focus->column_fields['subject'] = $mailrecord->_subject;
$focus->column_fields['description'] = $mailrecord->getBodyHTML();
$focus->column_fields['assigned_user_id'] = $linkfocus->column_fields['assigned_user_id'];
$focus->column_fields["date_start"]= date('Y-m-d', $mailrecord->_date);
$from=$mailrecord->_from[0];
$to = $mailrecord->_to[0];
$cc = (!empty($mailrecord->_cc))? implode(',', $mailrecord->_cc) : '';
$bcc= (!empty($mailrecord->_bcc))? implode(',', $mailrecord->_bcc) : '';
$flag=''; // 'SENT'/'SAVED'
//emails field were restructured and to,bcc and cc field are JSON arrays
$focus->column_fields['from_email'] = $from;
$focus->column_fields['saved_toid'] = $to;
$focus->column_fields['ccmail'] = $cc;
$focus->column_fields['bccmail'] = $bcc;
$focus->save('Emails');
$emailid = $focus->id;
$this->log("Created [$focus->id]: $mailrecord->_subject linked it to " . $linkfocus->id);
// TODO: Handle attachments of the mail (inline/file)
$this->__SaveAttachements($mailrecord, 'Emails', $focus);
return $emailid;
}
/**
* Save attachments from the email and add it to the module record.
*/
function __SaveAttachements($mailrecord, $basemodule, $basefocus) {
global $adb;
// If there is no attachments return
if(!$mailrecord->_attachments) return;
$userid = $basefocus->column_fields['assigned_user_id'];
$setype = "$basemodule Attachment";
$date_var = $adb->formatDate(date('YmdHis'), true);
foreach($mailrecord->_attachments as $filename=>$filecontent) {
$attachid = $adb->getUniqueId('vtiger_crmentity');
$description = $filename;
$usetime = $adb->formatDate($date_var, true);
$adb->pquery("INSERT INTO vtiger_crmentity(crmid, smcreatorid, smownerid,
modifiedby, setype, description, createdtime, modifiedtime, presence, deleted)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
Array($attachid, $userid, $userid, $userid, $setype, $description, $usetime, $usetime, 1, 0));
$issaved = $this->__SaveAttachmentFile($attachid, $filename, $filecontent);
if($issaved) {
// Create document record
$document = new Documents();
$document->column_fields['notes_title'] = $filename;
$document->column_fields['filename'] = $filename;
$document->column_fields['filestatus'] = 1;
$document->column_fields['filelocationtype'] = 'I';
$document->column_fields['folderid'] = 1; // Default Folder
$document->column_fields['assigned_user_id'] = $userid;
$document->save('Documents');
// Link file attached to document
$adb->pquery("INSERT INTO vtiger_seattachmentsrel(crmid, attachmentsid) VALUES(?,?)",
Array($document->id, $attachid));
// Link document to base record
$adb->pquery("INSERT INTO vtiger_senotesrel(crmid, notesid) VALUES(?,?)",
Array($basefocus->id, $document->id));
}
}
}
/**
* Save the attachment to the file
*/
function __SaveAttachmentFile($attachid, $filename, $filecontent) {
global $adb;
$dirname = $this->STORAGE_FOLDER;
if(!is_dir($dirname)) mkdir($dirname);
$description = $filename;
$filename = str_replace(' ', '-', $filename);
$saveasfile = "$dirname$attachid" . "_$filename";
if(!file_exists($saveasfile)) {
$this->log("Saved attachement as $saveasfile\n");
$fh = fopen($saveasfile, 'wb');
fwrite($fh, $filecontent);
fclose($fh);
}
$mimetype = MailAttachmentMIME::detect($saveasfile);
$adb->pquery("INSERT INTO vtiger_attachments SET attachmentsid=?, name=?, description=?, type=?, path=?",
Array($attachid, $filename, $description, $mimetype, $dirname));
return true;
}
}
?>
Step10: If you still face problems, and still cant get the update ticket functionality;
Check out the VTiger Forums.
[4]: http://i.stack.imgur.com/5ZU7Q.jpgemphasized text*emphasized text*
Related
I get a corrupted file when opening an email attachment sent with the PHP version of SendGrid mail
I am trying to send attachments with SendGrid through PHP, but keep getting a corrupted file error when I open the attachment. The error message "We're sorry. We can't open 'file.docx' because we found a problem with its contents" and when I click on the details of the error I see "The file is corrupt and cannot be opened" My code looks like the below: $sendGridLoginInfo = $contactViaEmail->getSendGridLoginInfo(); $sendgrid = new SendGrid($sendGridLoginInfo['Username'], $sendGridLoginInfo['Password']); $mail = new SendGrid\Mail(); //Add the tracker args $mail->addUniqueArgument("EmailID", $emailID); $mail->addUniqueArgument("EmailGroupID", $emailGroupID); /* * INSERT THE SUBSITUTIONS FOR SEND GRID */ foreach ($availableSubstitutions as $availableSubstitution) { $mail->addSubstitution("[[" . $availableSubstitution . "]]", $substitutions[$availableSubstitution]); } /* * ADD EACH EMAIL AS A NEW ADD TO * This makes it BCC (because each person gets their own copy) and each person gets their own individualized email. */ foreach ($emailInfo['SendToEmailAddress'] as $toEmail) { if ($sendToLoggedInUser) { $mail->addTo($adminEmailAddress); } else { $mail->addTo($toEmail); } $trashCount++; } //Set the subject $mail->setSubject($emailInfo['EmailSubject']); //Instantiate the HTML Purifier (for removing the html) $config = HTMLPurifier_Config::createDefault(); $config->set('HTML', 'Allowed', ''); $purifier = new HTMLPurifier($config); $mail->setText($purifier->purify($emailBody)); $mail->setHtml($emailBody); if ($emailInfo['AttachmentID']) { $sql = "SELECT AttachmentPath FROM EmailAttachments WHERE EmailAttachments.AttachmentID = :attachmentID"; if ($query = $pdoLink->prepare($sql)) { $bindValues = array(); $bindValues[":attachmentID"] = $emailInfo['AttachmentID']; if ($query->execute($bindValues)) { if ($row = $query->fetch(\PDO::FETCH_ASSOC)) { $attachment = ""; $mail->addAttachment($sitedb . $row['AttachmentPath']); } } } } if ($sendToLoggedInUser) { $mail->setFrom($adminEmailAddress); $mail->setReplyTo($adminEmailAddress); } else { $mail->setFrom($emailInfo['FromAddress']); $mail->setReplyTo($emailInfo['ReplyTo']); } $mail->setFromName($emailInfo['FromName']); $sendgrid->web->send($mail); I've played with the content type and everything else that I can think of and just cannot find out what is causing the attachments to be corrupted.
You need to create an attachment object to add an attachment, you can't use the path directly like you are. SendGrid requires files to be sent as base64 encoded strings. You'll need to create the attachment object, you could do this as a method: public function getAttachment($path) { if (!file_exists($path)) { return false; } $attachment = new SendGrid\Attachment; $attachment->setContent(base64_encode(file_get_contents($path))); $attachment->setType(mime_content_type($path)); $attachment->setFilename(basename($path)); $attachment->setDisposition('attachment'); return $attachment; } Then add it to your email: $attachment = $this->getAttachment($sitedb . $row['AttachmentPath']); if ($attachment instanceof SendGrid\Attachment) { $mail->addAttachment($attachment); }
Laravel 4: Mail Send with array to CC gives error of does not comply with RFC 2822, 3.6.2
This drive me crazy all the time... I tried read all the stuff regarding SwiftMailer for Laravel including fixes from other errors base on subject, but I do not get how I am still getting error passing array of email address. Is there a way to determine how the CC display my email addresses? Whenever I print_r it, it display “name#domain.com; name2#domain.com “. // current logged id $user_id = $id; // match all current logged id to all assets // if investment type is present, get property id $asset = ClientPropertyManagement::where('assets.client_id', '=', $user_id)->get(); foreach( $asset as $assets ) { if( $assets->investment_type == "TIC" ) { $properties[] = $assets->property_id; } } // if property id is present, connect to property table // if connected and match id, get property manager emails if( !empty($properties) ){ $property = DB::table('property')->whereIn('id', $properties)->get(); foreach( $property as $p ){ $contact[] = $p->property_mgmt_contact; } } // if property managers are present, filter // name#domain.com; name2#domain.com if( !empty($contact) ) { $property_contact = implode(', ', array_filter(array_unique($contact))); } print_r($property_contact); // output: "name#domain.com; name2#domain.com " //send email to owner and other property manager Mail::send('_dash.emails.profile', $contacts, function ($message) { $ownerEmail = "name#gmail.com"; $ownerName = "WebMail Information"; $recipient_name = Request::get('firstname') .' '. Request::get('lastname'); $recipient_email = explode(';', Input::get('email')); $message->from($recipient_email[0],$recipient_name); $message->cc($property_contact); // send property all managers $message->to($ownerEmail,$ownerName)->subject("Profile Update"); }); Note: After I dump dd($property_contact) the value was null... how come? Even if I paste the code inside Mail::send still empty.
I forgot to add use ($variable) inside my Mail::send to pass my variable outside Mail::send. //send email to owner and other property manager Mail::send('_dash.emails.profile', $contacts, function ($message) use ($property_contact) { $ownerEmail = "name#gmail.com"; $ownerName = "WebMail Information"; $recipient_name = Request::get('firstname') .' '. Request::get('lastname'); $recipient_email = explode(';', Input::get('email')); $message->from($recipient_email[0],$recipient_name); $message->cc($property_contact); // send property all managers $message->to($ownerEmail,$ownerName)->subject("Profile Update"); });
Adding Address Fields to the Registeration form in Prestashop
When a customer or user registers, I want to capture the address details in one click and save that in ps_address table , ie when he clicks on the register button his address details must be also saved to the ps_address table , how to do this? I have managed to customize the registration form and able to plug the address details form to my registration form as shown in the attached image : Now what I am stuck with is : when am clicking on the Register button ,the address field details are not saved in the database and I am getting server error What I tried to do is ,I created a new function called processPostAddress and I am calling processPostAddress from processSubmitAccount() in controller/front/Authcontroller.php page before the redirection to the account page. $this->processPostAddress(); //// custom function call Tools::redirect('index.php?controller='.(($this->authRedirection !== false) ? urlencode($this->authRedirection) : 'my-account')); Below is the custom function which i created in controller/front/Authcontroller.php page public function processPostAddress() { if($this->context->customer->id_customer!=''){ $address = new Address(); $address->id_customer = 40; $address->firstname = trim(Tools::getValue('firstname')); $address->lastname = trim(Tools::getValue('lastname')); $address->address1 = trim(Tools::getValue('address1')); $address->address2 = trim(Tools::getValue('address2')); $address->postcode = trim(Tools::getValue('postcode')); $address->city = trim(Tools::getValue('city')); $address->country = trim(Tools::getValue('country')); $address->state = trim(Tools::getValue('state')); $address->phone = trim(Tools::getValue('phone')); $address->phone_mobile = trim(Tools::getValue('phone_mobile')); $address->add(); // This should add the address to the addresss table } } Please help me or tell me if I am doing anything wrong or how to achieve this
I solved it by adding $address->alias, since alias was required and was validated . Also in order to save in the database I modified $address->add(); to $address->save(); public function processPostAddress() { ///Address::postProcess(); // Try this for posting address and check if its working // Preparing Address $address = new Address(); $this->errors = $address->validateController(); $address->id_customer = (int)$this->context->customer->id; $address->firstname = trim(Tools::getValue('firstname')); $address->lastname = trim(Tools::getValue('lastname')); $address->address1 = trim(Tools::getValue('address1')); $address->address2 = trim(Tools::getValue('address2')); $address->postcode = trim(Tools::getValue('postcode')); $address->city = (int)trim(Tools::getValue('city')); $address->country = (int)trim(Tools::getValue('country')); $address->state = (int)trim(Tools::getValue('state')); $address->phone = trim(Tools::getValue('phone')); $address->alias = "My Default Address"; // Check the requires fields which are settings in the BO $this->errors = array_merge($this->errors, $address->validateFieldsRequiredDatabase()); // Don't continue this process if we have errors ! if (!$this->errors && !$this->ajax) { return; }else{ // Save address $address->save(); } }
Trying to get emails from database using Yiimail
A little background, I'm creating a simple function that emails all users whenever the admin of a blog creates a new announcement. I want to gather all emails using an sql query and inputting them all inside the message body or perhaps looping sending the emails one at a time (though that may seem like it would take longer). So far this is my code: public function emailAll() { $this->set_mail_settings(); $message = new YiiMailMessage; $request = Yii::app()->db->createCommand(" SELECT email FROM persons WHERE party_id ")->queryRow(); $message->subject = 'Star Cruises - Login Information'; $message->addTo('sendTo#someone.com'); $message->from = Yii::app()->params['adminEmail']; Yii::app()->mail->send($message); exit(); } private function set_mail_settings() { $sysParam = SystemParameters::model()->getSystemParameters( array("smtp_host", "smtp_port", 'smtp_user','smtp_password') ); Yii::app()->mail->transportOptions['username'] = $sysParam['smtp_user']; Yii::app()->mail->transportOptions['password'] = $sysParam['smtp_password']; Yii::app()->mail->transportOptions['host'] = $sysParam['smtp_host']; Yii::app()->mail->transportOptions['port'] = $sysParam['smtp_port']; } The emailAll() function is called whenever an email is used. My problem is the $request. I don't know how I would gather all the emails and putting them into the $message->addTo(); UPDATE: I was doing it fine until I reached this point: public function emailAll() { $this->set_mail_settings(); $message = new YiiMailMessage; $emails = Yii::app()->db->createCommand("SELECT group_concat(email) as em FROM persons")->queryRow(); $email_ids = explode(",",$emails["em"]); $message->setBcc($email_ids); $message->setBody('Sample'); $message->subject = 'New Announcement!'; //$message->addTo('blah#blah.com'); $message->from = Yii::app()->params['adminEmail']; Yii::app()->mail->send($message); } private function set_mail_settings() { $sysParam = SystemParameters::model()->getSystemParameters( array("smtp_host", "smtp_port", 'smtp_user','smtp_password') ); Yii::app()->mail->transportOptions['username'] = $sysParam['smtp_user']; Yii::app()->mail->transportOptions['password'] = $sysParam['smtp_password']; Yii::app()->mail->transportOptions['host'] = $sysParam['smtp_host']; Yii::app()->mail->transportOptions['port'] = $sysParam['smtp_port']; } Then I got an error on this line from YiiMail.php: 189 $msg = 'Sending email to '.implode(', ', array_keys($message->to))."\n". And it stated that : array_keys() expects parameter 1 to be array, null given. I understand what it wants, but I don't understand WHY this error occurred?
You can get all email ids with use of below query and use BCC instead of To for security reason. $emails = Yii::app()->db->createCommand("SELECT group_concat(email) as em FROM persons WHERE party_id = $party_id")->queryRow(); $email_ids = explode(",",$emails["em"]); $message->setBcc($email_ids); // use bcc to hide email ids from other users $message->addTo("noreply#yourdomain.com"); //as To is required, set some dummy id or your own id.
php - imap - moving emails on antoher account
I am working on a script that downloads emails and stores them in a db, I usually receive thousands of emails on this account, once downloaded the mails are deleted. Being paranoic, I want to have at least one month backup of my emails, but I cannot clutter my main mailbox address leaving them in there. So i need to move the mails (via php code) from one mailbox to another. I came up with this solution that uses imap_append(). This solution, however recreates the email, and does not really move it. Do you have any suggestions or alternative ways of doing this? Remember: it must be done in php, because I need to integrate it in my readmail script. I have already seen this thread where a fetchmail solution was proposed Here follows the code I wrote for this task <?php /** * Conn params */ $fromMboxServerPath = "{imap.from.server/notls/imap:143}"; $fromMboxMailboxPath = "INBOX"; $fromMboxMailAddress = "login"; $fromMboxMailPass = "pass"; $toMboxServerPath = "{imap.to.server/notls/imap:143}"; $toMboxMailboxPath = "INBOX"; $toMboxMailAddress = "login"; $toMboxMailPass = "pass"; $fromMboxConnStr = $fromMboxServerPath.$fromMboxMailboxPath; $toMboxConnStr = $toMboxServerPath.$toMboxMailboxPath; $fetchStartSeq = 1; $fetchEndSeq = 10; function myLog($str) { echo "Log [".date('Y-m-d H:i:s')."]: $str\n"; } myLog("Connecting to mailbox"); function mboxConn($connstr,$addr,$pass) { if(!($mbox = #imap_open($connstr, $addr, $pass))) { myLog("Error: ".imap_last_error()); die; } else { myLog("Connected to: $addr $connstr"); return $mbox; } } function mboxCheck($mbox) { if(!($mbox_data = imap_check($mbox))) { myLog("Error: ".imap_last_error()); die; } else { myLog("Mailbox check ".$mbox_data->Mailbox." OK"); myLog($mbox_data->Nmsgs." messages present"); return $mbox_data->Nmsgs; } } $fromMbox = mboxConn($fromMboxConnStr, $fromMboxMailAddress, $fromMboxMailPass); $toMbox = mboxConn($toMboxConnStr, $toMboxMailAddress, $toMboxMailPass); $fromMboxCount = mboxCheck($fromMbox); $toMboxCount = mboxCheck($toMbox); /** * Loop on mails */ $fetchStartUID = imap_uid($fromMbox,$fetchStartSeq); if ($fromMboxCount < $fetchEndSeq) { $fetchEndSeq = $fromMboxCount; } $fetchEndUID = imap_uid($fromMbox,$fetchEndSeq); /** * Loop on mails */ myLog("Do stuff and backup from UID [$fetchStartUID] to UID [$fetchEndUID]"); for ($i=$fetchStartSeq;$i<=$fetchEndSeq;$i++) { $pfx = "Msg #$i : "; $h = imap_header($fromMbox, $i); $fh = imap_fetchheader($fromMbox, $i); $fb = imap_body($fromMbox, $i); $message = $fh.$fb; $msgUID = imap_uid($fromMbox,$i); $struct = imap_fetchstructure ($fromMbox, $i); /** * We do some logging */ myLog($pfx."UID [".$msgUID."] SEQ [".imap_msgno($fromMbox,$msgUID)."] Flags: [". $h->Unseen . $h->Recent . $h->Deleted . $h->Answered . $h->Draft . $h->Flagged."]"); myLog($pfx."From: [". htmlspecialchars($h->fromaddress) . "] To: [".htmlspecialchars($h->toaddress)."]"); myLog($pfx."Subject: [$h->subject]"); /** * Here you do whaterver you need with your email */ /** * Backup email */ if (!($ret = imap_append($toMbox,$toMboxServerPath.$toMboxMailboxPath,$message))) { myLog("Error: ".imap_last_error()); die; } else { myLog("everything ok, mail [$fetchStartUID:$fetchEndUID] downloaded and moved in $newMailboxNameMOVE"); } } /** * End */ imap_close($fromMbox); imap_close($toMbox); myLog("Connection closed"); ?>
First, IMAP does not have a MOVE command only copy but even if it did you can copy from one IMAP server to another directly. Why not use a subfolder in the account for backups. Download them to your local machine then COPY them to the subfolder and then DELETE them from the INBOX. COPY and DELETE are imap server side commands so they don't have to leave the server to do the "move" If both accounts are on the same server there is another option, allow access to the backup account's INBOX to the primary account user. Then you can use server side copy/delete to move it to the backup folder. Not all IMAP servers allow for shared folders. php does have a imap_move function but I assume it does a copy/delete.
I don't know any other solution like PHP. But for your code and testing you should use: $fromMboxServerPath = "{imap.from.server/notls/imap/readonly:143}"; //ReadOnly in imap_append() you should give the date from emailheader. see PHP Manual: http://php.net/manual/en/function.imap-append.php after that you will have a 1to1 copy of your mail in the target IMAP-Server.
Why separate account and all the hassle that will be involved? Can't you either a) backup the mail account using standard backup tools like, eg. rdiff-backup? b) back them up in the db? or even c) create an alias so that emails go to both accounts and you have different criteria for removing mails from both accounts (ie. keep them for one more month in the backup account)