Debug Swift Mailer in PrestaShop 1.6 - prestashop-1.6

Occasionally sending mails fail with the Mail::send function of PrestaShop. I use a external mailserver, and the responsible person there told me that no request was received for sending any mails (I find this strange though). So, I made a little logger doing the following:
if ( !Mail::send() )
// logging details here here..
The Mail::send returns false correctly. Now I would like to know the reason. Therefore I would like to log information about the connection in SwiftMailer. Could someone give me any clues how to solve this in a simple manor (not with SwiftMailer plugins, if possible).
Swift Mailer version: 3.3.2

If you set $die param to true you will cause that script stop and a bad experience for customer while buying or admin while changing order status, etc. You should check the following:
Check if email sending fails on specific email template. If true, you could have a problem with template structure, parameters passed, html rendering, etc.
Every error inside Mail::Send funtion is logged in Prestashop Logs. So you should check it there. You could know every possible error identifyng this kind of code inside function Mail::Send: Tools::dieOrLog(Tools::displayError('Error: invalid SMTP server or SMTP port'), $die);
Specific Swift exceptions are logged with this code: PrestaShopLogger::addLog('Swift Error: ' . $e->getMessage(), 3, null, 'Swift_Message'); so it should appear in Prestashop Logs too.
Anyway, Swift has his own log in class Swift_Log_DefaultLog. You can find it at \tools\swift\Swift\Log\DefaultLog.php. You could modify add or dump function to save logs to an specific file or similar.
Good luck.

Set $die parameter true to display the error. You will need _PS_MODE_DEV_ set to true to see it.
/**
* Send Email
*
* #param int $id_lang Language ID of the email (to translate the template)
* #param string $template Template: the name of template not be a var but a string !
* #param string $subject Subject of the email
* #param string $template_vars Template variables for the email
* #param string $to To email
* #param string $to_name To name
* #param string $from From email
* #param string $from_name To email
* #param array $file_attachment Array with three parameters (content, mime and name). You can use an array of array to attach multiple files
* #param bool $mode_smtp SMTP mode (deprecated)
* #param string $template_path Template path
* #param bool $die Die after error
* #param string $bcc Bcc recipient
* #return bool|int Whether sending was successful. If not at all, false, otherwise amount of recipients succeeded.
*/
public static function Send($id_lang, $template, $subject, $template_vars, $to,
$to_name = null, $from = null, $from_name = null, $file_attachment = null, $mode_smtp = null,
$template_path = _PS_MAIL_DIR_, $die = false, $id_shop = null, $bcc = null, $reply_to = null)
Alternatively you could go to backoffice and menu Advanced Parameters -> Logs, type in a Message filter: error and search for results. It's not guaranteed it will show you only email errors but it narrows it down a lot.

It is not possible to tell you the reason for failure of Mail::send() function. There can be multiple reasons for the failure.
There are 12 lines of code in that returns false in the Mail::send() function, each having a different condition. You need to debug the function to find the exact reason.
You can find the Mail::send() function in Mail.php file at /classes/Mail.php
Tip: You can add log with every 'return false;' statement in the function to check which of them is getting executed.

Related

Access session value in gatling checks

I use gatling to send data to an ActiveMQ. The payload is generated in a separate method. The response should also be validated. However, how can I access the session data within the checks
check(bodyString.is()) or simpleCheck(...)? I have also thought about storing the current payload in a separate global variable, but I don't know if this is the right approach. My code's setup looks like this at the moment:
val scn = scenario("Example ActiveMQ Scenario")
.exec(jms("Test").requestReply
.queue(...)
.textMessage{ session => val message = createPayload(); session.set("payload", payload); message}
.check(simpleCheck{message => customCheck(message, ?????? )})) //access stored payload value, alternative: check(bodystring.is(?????)
def customCheck(m: Message, string: String) = {
// check logic goes here
}
Disclaimer: providing example in Java as you don't seem to be a Scala developper, so Java would be a better fit for you (supported since Gatling 3.7).
The way you want to do things can't possibly work.
.textMessage(session -> {
String message = createPayload();
session.set("payload", payload);
return message;
}
)
As explained in the documentation, Session is immutable, so in a function that's supposed to return the payload, you can't also return a new Session.
What you would have to do it first store the payload in the session, then fetch it:
.exec(session -> session.set("payload", createPayload()))
...
.textMessage("#{payload}")
Regarding writing your check, simpleCheck doesn't have access to the Session. You have to use check(bodyString.is()) and pass a function to is, again as explained in the documentation.

Is there a way to preserve a signature in RDOMail.Reply like MailItem.Reply does?

I tried obtaining the reply to the mail by using RDOMail.Reply method.
However, after inspecting the returned object, I've noticed that the signature is not part of the HTMLBody property, as it is when using method MailItem.Reply (which I'm not using because it throws 0x80004004 (E_ABORT) exception). Also, attachments that would be needed for the signature if it contains images are not preserved as they are with MailItem.Reply.
I've tried applying the signature separately, using Signature object. This adds signature to the HTMLBody, but doesn't use the _MailAutoSig attribute to mark the signature part therefore if I select "Change signature" from Outlook Ribbon, signature doesn't get replaced because Outlook has no way of knowing it is a signature.
Is there a way to obtain reply from RDOMail that would contain signature Outlook knows how to replace?
var rdoMail = session.GetMessageFromID(entryid);
var reply = rdoMail.Reply();
reply.HTMLBody = "";
var Account = session.Accounts.GetOrder(rdoAccountCategory.acMail).Item(1);
var signature = Account.ReplySignature;
signature.ApplyTo(reply, false);
reply.Save();
This is a known issue/case when dealing with Extended MAPI code and it is not related to Redemption only. See Messages that are created outside Outlook do not include the default Outlook email signature for more information.
Your choices are:
Mimic the Outlook behavior by adding all the necessary parts like _MailAutoSig attribute to the message body.
Use the Outlook object model with the Reply method and then getting the Redemption equivalent by using the GetRDOObjectFromOutlookObject method. But as far as I can tell, looking at the exception you get, it is not possible because the code is used from a secondary thread, right?
You can use its RDOAccount object (accessible in any language, including VBA). New message signature name is stored in the 0x0016001F property, reply signature is in 0x0017001F.
You can also use the RDOAccount.ReplySignature and NewSignature properties.
Redemption also exposes RDOSignature.ApplyTo method that takes a pointer to the RDOMail object and inserts the signature at the specified location correctly merging the images and the styles:
set Session = CreateObject("Redemption.RDOSession")
Session.MAPIOBJECT = Application.Session.MAPIOBJECT
set Drafts = Session.GetDefaultFolder(olFolderDrafts)
set Msg = Drafts.Items.Add
Msg.To = "user#domain.demo"
Msg.Subject = "testing signatures"
Msg.HTMLBody = "<html><body>some <b>bold</b> message text</body></html>"
set Account = Session.Accounts.GetOrder(2).Item(1) 'first mail account
if Not (Account Is Nothing) Then
set Signature = Account.NewMessageSignature
if Not (Signature Is Nothing) Then
Signature.ApplyTo Msg, false 'apply at the bottom
End If
End If
Msg.Send

Consolibyte QuickBooks PHP Library - How Do You Pass Parameters To Queued Functions?

I am looking to add a customer to my QB installation using the Consolibyte PHP library. I know that I need to initialize and queue up my requests by using the following:
$Queue = new QuickBooks_WebConnector_Queue('mysql://root:password#localhost/my_database');
$Queue->enqueue(QUICKBOOKS_ADD_CUSTOMER, $id_value);
In the above, I am merely passing in a unique ID when I queue the request ($id_value). Looking at the _quickbooks_customer_add_request() method, I see that there are 9 parameters for the function. How are these parameters set when I call $Queue->enqueue()?
Here's the function definition:
->enqueue($action, $ident = null, $priority = 0, $extra = null, $user = null, $qbxml = null, $replace = true)
From here:
https://github.com/consolibyte/quickbooks-php/blob/master/QuickBooks/WebConnector/Queue.php#L208
Documentation:
* #param string $action An action to be performed within QuickBooks (see the qbXML and QuickBooks SDK documentation, i.e.: "CustomerAdd", "InvoiceAdd", "CustomerMod", etc.)
* #param mixed $ident A unique identifier (if required) for a record being operated on (i.e. if you're doing a "CustomerAdd", you'd probaly put a unique customer ID number here, so you're SOAP handler function knows which customer it is supposed to add)
* #param integer $priority The priority of the update (higher priority actions will be pushed to QuickBooks before lower priority actions)
* #param array $extra If you need to make additional bits of data available to your request/response functions, you can pass an array of extra data here
* #param string $user The username of the QuickBooks Web Connector user this item should be queued for
* #param boolean $replace Whether or not to replace any other currently queued entries with the same action/ident

Google Form/Sheet - Skip blank email google script

This is a similar question to this link, but slightly different:
Skipping blank emails in Google Apps Script Mail Merge
I have a form/sheet set up that, when the users fills out the form, it generates a receipt email (does not contain the form contents as some receipts do) that is then sent to the recipient. However when the user leaves this field blank I get a form trigger error, which is understandable why the script didn't finish. I am trying to figure out how to keep the script from attempting to send an email when the recipient/email field is blank. Unfortunately, making the email field required on the form is not an option since, oddly, not everyone would have an email address (if this were an option I would certainly just require an email address to be entered).
I have tried the following code snippet based on the link provided above.
// Send Email to recipient(s) declared above in #var sendEmail
if (e.values[11] != null) {
var sendEmail = e.values[11]; //email field column
var subject = "subject message";
var body = "body message";
MailApp.sendEmail(sendEmail, subject, body, {
name: "Community Home Health Care",
body: body,
noReply: true,
})
I have also tried instead of
(e.values[11] != null)
using
(e.values[11] != "")
The remaining code I have omitted (goes above what I have shown) simply takes the form field responses and generates a document converted to a PDF which works as expected. The email section also works, just trying to eliminate the failed script emails I get occasionally.
Thanks
First is an assumption that 12 items are passed (0 through 11) and the email is the last item to be passed. If that is the case, then test that the item is defined with:
if(typeof e.values[11] !== 'undefined')
If you are using the Mail Merge Tutorial linked to in the post you linked to, and using the getRowsData() function to get your form responses, you should be able to use the Header of the column containing the email address such as e.values.emailAddress and get:
if(typeof e.values.emailAddress !== 'undefined')
This may vary based on how your data is defined.

Read Gmail XOAUTH mails without marking it read

I'm trying to read email from GMail using gmail-xoauth Gem. I want to read the email and leave its unread status.
First, I tried reading just the header. Works.
imap = Net::IMAP.new('imap.gmail.com', 993, usessl = true, certs = nil, verify = false)
imap.authenticate('XOAUTH2', email, access_token)
imap.select('INBOX')
imap.search(["SINCE", since]).each do |message_id|
msg = imap.fetch(message_id,'RFC822.HEADER')[0].attr['RFC822.HEADER']
mail = Mail.read_from_string msg
puts mail.subject
end
Now, I want to read the body/text of the Email without marking it read.
This maybe be very late but I will leave it here for anyone else that stumbles onto this. If, for what ever reason you want to read the email and leave the flags intake, use:
imap.examine('INBOX')
instead of:
imap.select('INBOX')
From the Net::IMAP doc
Sends a EXAMINE command to select a mailbox so that messages in the mailbox can be accessed. Behaves the same as select(), except that the selected mailbox is identified as read-only.
Based on the documentation you need to use the store method. The documentation mentions:
store(set, attr, flags)
Sends a STORE command to alter data associated with messages in the mailbox, in particular their flags. The set parameter is a number or an array of numbers or a Range object. Each number is a message sequence number. attr is the name of a data item to store: ‘FLAGS’ means to replace the message’s flag list with the provided one; ‘+FLAGS’ means to add the provided flags; and ‘-FLAGS’ means to remove them. flags is a list of flags.
The return value is an array of Net::IMAP::FetchData. For example:
p imap.store(6..8, "+FLAGS", [:Deleted])
#=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
#<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
#<Net::IMAP::FetchData seqno=8, attr={"FLAGS"=>[:Seen, :Deleted]}>]
So you have to remove the :Seen flag
imap.store(message_id, "-FLAGS", [:Seen])

Resources