ZF2 mail error Too many RSET commands - zend-framework2

I have to send a lot of emails distributed over the whole day with ZF2 and I'm using Zend\Mail\Transport\Smtp. I have the mails in a queue table and once a minute I want to send them. Everything works fine until 5th email, where I receive an error : Zend\Mail\Protocol\Exception\RuntimeException
4.7.0 Too many RSET commands; closing connection
I guess this is coming from the smtp server. But why does ZF2-Smtp reset each message? I don't know where to start debugging the problem and if you need more informations just let me know. Thx for any help...
What I'm using is:
$transport = new SmtpTransport();
$options = new SmtpOptions(array(
'host' => $config['mail_options']['server'],
'port' => $config['mail_options']['port'],
'connection_class' => 'login',
'connection_config' => array(
'username' => $config['mail_options']['smtp_user'],
'password' => $config['mail_options']['smtp_password'],
'ssl' => $config['mail_options']['ssl'],
),
));
foreach ($queuedMails as $queuedMail) {
$message = new Message();
$message->addTo($data['to'])
->addFrom($config['mail_options']['from'], $config['mail_options']['from_name'])
->setSubject($data['subject'])
->setBody(utf8_decode($data['body']))
->setEncoding('utf-8');
$transport->setOptions($options);
$transport->send($message);enter code here
}
Should I place the $transport into the foreach?

Related

omniauth-saml nil values in info hash

I'm working with devise and omniauth-saml, following the instructions from https://github.com/PracticallyGreen/omniauth-saml and the omniauth Facebook example https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
I have a simplesamlphp server running, using the metadata provided by omniauth, and everything seems to be connecting properly, but the response from the simplesaml server has nil values for email, first_name, last_name and name. The weird thing is that it is returning the email and name values, just not in a useful part of the response (see below - super#man.com is the email, Clark Kent is the name)
The weird thing is that I get these nil values with both omniauth-saml and devise-saml-authenticatable gems, but I think my simplesamlphp server is configured properly.
The response from omniauth looks like this:
#<OmniAuth::AuthHash credentials=#<OmniAuth::AuthHash> extra=#<OmniAuth::AuthHash raw_info=#<OneLogin::RubySaml::Attributes:0x007fc695850148 #attributes={"urn:oid:0.9.2342.19200300.100.1.1"=>["super#man.com"], "urn:oid:2.16.840.1.113730.3.1.241"=>["Clark Kent"], "fingerprint"=>"FINGERPRINT REMOVED"}>> info=#<OmniAuth::AuthHash::InfoHash email=nil first_name=nil last_name=nil name=nil> provider="saml" uid="_ca76f49ccb6ccce7827111ae1ff0563f534f0a4d1a">
The simplesamlphp config looks like this:
$metadata['http://localhost:3000/saml/users/auth/saml/metadata'] = array(
'AssertionConsumerService' => 'http://localhost:3000/saml/users/auth/saml/callback',
'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:email',
'simplesaml.nameidattribute' => 'email',
);
I am sure that there are good values for the user in the database, and when I test authentication on the IDP itself, everything works as expected.
I solved this. The problem was that I was trying to use values that didn't use the ldap attribute names.
I changed my sp metadata as follows (after modifying my model to use first_name and last_name instead of just name)
$metadata['http://localhost:3000/saml/users/auth/saml/metadata'] = array(
'AssertionConsumerService' => 'http://localhost:3000/saml/users/auth/saml/callback',
'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:email',
'authproc' => array(
95 => array(
'class' => 'core:AttributeMap',
'givenName' => 'first_name',
'sn' => 'last_name',
'mail' => 'email',
),
96 => array(
'class' => 'core:AttributeLimit',
'email', 'first_name', 'last_name'
),
),
'simplesaml.nameidattribute' => 'email',
);

Connecting to Twilio SMS via a Proxy in PHP

I'm testing Twilio to use as our SMS solution however I'm having issues getting it to work behind our proxy server.
I've tried:
$twiliohttp = new Services_Twilio_TinyHttp(
"https://api.twilio.com",
array("curlopts" => array(
CURLOPT_USERAGENT => self::USER_AGENT,
CURLOPT_HTTPHEADER => array('Accept-Charset: utf-8'),
CURLOPT_CAINFO => dirname(__FILE__) . '/cacert.pem',
CURLOPT_PROXY => '3.X.X.X:9400',
))
);
$client = new Services_Twilio($account_sid, $auth_token, null, $twiliohttp );
$message = $client->account->messages->sendMessage(
'+441432XXXX31', // From a Twilio number in your account
'+44776XXXX712', // Text any number
"Hello monkey!"
);
I then get the error: Fatal error: Cannot access self:: when no class scope is active in /var/www/twiliosms.php on line 16
So I modified the Twilio.php file modifying the curlopts array to add:
CURLOPT_PROXY => '3.X.X.X:9400',
and calling Twilio with:
$client = new Services_Twilio($account_sid, $auth_token );
$message = $client->account->messages->sendMessage(
'+4414XXXXXXX1', // From a Twilio number in your account
'+4477XXXXXXX2', // Text any number
"Hello monkey!"
);
But I then get the error:
Fatal error: Uncaught exception 'Services_Twilio_RestException' with message 'Could not decode response body as JSON. This likely indicates a 500 server error' in /var/www/GE/includes/SMS/Twilio.php:288
Stack trace:
#0 /var/www/GE/includes/SMS/Twilio.php(181): Base_Services_Twilio->_processResponse(Array)
#1 /var/www/GE/includes/SMS/Twilio/ListResource.php(92): Base_Services_Twilio->createData('/2010-04-01/Acc...', Array)
#2 /var/www/GE/includes/SMS/Twilio/Rest/Messages.php(24): Services_Twilio_ListResource->_create(Array)
#3 /var/www/GE/includes/SMS/Twilio/Rest/Messages.php(71): Services_Twilio_Rest_Messages->create(Array)
#4 /var/www/GE/twiliosms.php(35): Services_Twilio_Rest_Messages->sendMessage('+441432233131', '+447766205712', 'Hello monkey!')
#5 {main}
thrown in /var/www/GE/includes/SMS/Twilio.php on line 288
Any ideas how to make this solution work through a proxy server that doesn't allow inbound connections?
Thanks in advance.
Ricky from Twilio here.
Although I couldn't test with your exact proxy setup I think the first solution you tried will work if you hardcode the user agent. For example:
$twiliohttp = new Services_Twilio_TinyHttp(
"https://api.twilio.com",
array("curlopts" => array(
CURLOPT_USERAGENT => "Twilio Proxy/1.0",
CURLOPT_HTTPHEADER => array('Accept-Charset: utf-8'),
CURLOPT_CAINFO => dirname(__FILE__) . '/cacert.pem',
CURLOPT_PROXY => '3.X.X.X:9400',
))
);
You also may need to make the modification to the TinyHttp library shown here.
Many thanks to RickyRobinett this is how to resolve the issue, I post this answer with the full solution so people don't have to trove through the badly formatted comments.
Update TinyHttp in line with: https://github.com/camuthig/twilio-php/commit/20d4f3c4479c93894866f498e89a0f13cf16d6bf
$twiliohttp = new Services_Twilio_TinyHttp(
"https://api.twilio.com",
array("curlopts" => array(
CURLOPT_USERAGENT => "Twilio Proxy/1.0",
CURLOPT_HTTPHEADER => array('Accept-Charset: utf-8'),
CURLOPT_CAINFO => 'includes/SMS/cacert.pem',
CURLOPT_PROXY => 'X.X.X.X:9400',
))
);
$client = new Services_Twilio($account_sid, $auth_token, null, $twiliohttp );
If you don't have the cacert.pem then checkout this post https://stackoverflow.com/a/31297747/1697288

OAuth signature generation using HMAC-SHA1?

I apologize for asking so many questions but none of them seem to be getting answered and I really need help on this. I'm using LTI to integrate my program into a learning management system, and I need to authenticate using OAuth. I have no trouble generating a signature following the guidelines here but the signature I generate never matches the one passed to me by the LMS, and I can't figure out for the life of me why they never match. I'm hoping that it's something I'm oblivious to, but I really need some assistance on this.
When I launch my program from the LMS, I am sent this array via POST in what is called the LTI launch:
array(
'launch_presentation_locale' => 'EN-US__',
'tool_consumer_instance_guid' => 'key',
'tool_consumer_instance_name' => 'MyProgram',
'tool_consumer_instance_description' => 'MyProgram',
'tool_consumer_instance_contact_email' => 'johndoe#email.com',
'tool_consumer_info_version' => '10.3.0 SP5',
'tool_consumer_info_product_family_code' => 'desire2learn',
'context_id' => '2440554',
'context_title' => 'ContextTitle',
'context_label' => 'ContextTitle',
'context_type' => '',
'user_id' => 'USER_ID',
'roles' => 'None',
'lis_person_name_given' => 'John',
'lis_person_name_family' => 'Doe',
'lis_person_name_full' => 'John Doe',
'lis_person_contact_email_primary' => 'johndoe#email.com',
'ext_tc_profile_url' => 'https://profileurl.com',
'ext_d2l_token_id' => '123456789',
'ext_d2l_link_id' => '1234',
'ext_d2l_token_digest' => 'AbCdEfGhIjKlMnOpQrStUvWxYzi=',
'resource_link_id' => '',
'resource_link_title' => 'MyProgram',
'resource_link_description' => 'MyProgram',
'lis_result_sourcedid' => 'abcdefgh-ijkl-mnop-qrst-uvwxyz012345',
'lis_outcome_service_url' => 'https://outcomeserviceurl.com',
'lti_version' => 'LTI-1p0',
'lti_message_type' => 'basic-lti-launch-request',
'oauth_version' => '1.0',
'oauth_nonce' => '123456789',
'oauth_timestamp' => '1234567890',
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_consumer_key' => 'key',
'oauth_callback' => 'about:blank',
'oauth_signature' => 'eFUR8O5xVydLrj4PDj37nF4cq6A=',
'basiclti_submit' => 'Launch Endpoint with BasicLTI Data'
);
Here is what I'm trying. I've added comments to clarify the steps:
// Set variables that are required for the signature to be generated.
$OAUTH_KEY = 'key';
$OAUTH_SECRET = 'secret';
$httpMethod = 'POST';
$SITE_URL = 'https://localhost/test.php';
// make array copy of entire POST data, remove the 'oauth_signature' field as specified in the oauth spec from the copy array, then sort alphabetically. After that, url encode the key/value of each item in the copy array and store into a string for later use.
$request_parameter_array = $_POST;
unset($request_parameter_array['oauth_signature']);
ksort($request_parameter_array);
$request_parameter_str = '';
foreach($request_parameter_array as $key => $value) {
$request_parameter_str .= rawurlencode($key) . '=' . rawurlencode($value) . '&';
}
// create the signature base string (string variable that the actual signature is created from) by following these steps from the OAuth documentation:
// 1. The HTTP request method in uppercase. For example: "HEAD",
// "GET", "POST", etc. If the request uses a custom HTTP method, it
// MUST be encoded (Section 3.6).
// 2. An "&" character (ASCII code 38).
// 3. The base string URI from Section 3.4.1.2, after being encoded
// (Section 3.6).
// 4. An "&" character (ASCII code 38).
// 5. The request parameters as normalized in Section 3.4.1.3.2, after
// being encoded (Section 3.6).
$key = rawurlencode($OAUTH_SECRET) . '&';
$signature_base = strtoupper($httpMethod) . '&' . rawurlencode($SITE_URL) . '&';
$signature_base .= rawurlencode($request_parameter_str);
$signature = base64_encode(hash_hmac("sha1", $signature_base, $key, true));
echo $signature;
I guess my own stupidity was the issue, here. The issue was arising from D2L itself because I misunderstood what the difference was between using a tool link vs. a tool provider for my integrations. I literally deleted my tool provider and went with a tool link and now I'm able to authenticate every time.
Turns out there wasn't a problem with the code at all here.

Unable to enable crypto on TCP connection api.mysite.com on Zend

I was creating a module application for Zend Framework 2. When I try to send a post request to my server with the necessary details, I get the error "Unable to enable crypto on TCP connection api.mysite.com".
Earlier, I was getting the error "Unable to enable crypto on TCP connection api.mysite.com: make sure the "sslcafile" or "sslcapath" option are properly set for the environment."
On googling, I found I should set sslverifypeer to false. After doing this, I was left with the 1st part of the sentence "Unable to enable crypto on TCP connection api.mysite.com."
Not getting idea where I could be wrong.
Under previous exceptions, I get "stream_socket_enable_crypto(): this stream does not support SSL/crypto"
Please see this note in the docs: http://framework.zend.com/manual/2.3/en/modules/zend.http.client.html#connecting-to-ssl-urls . You shouldn't set sslverifypeer unless the site you're connecting to doesn't have a valid SSL certificate. Instead, set sslcapath as the error suggests. This gives PHP a way of validating the SSL certificate supplied by the host you're connecting to.
This is due to your site trying to communicate with a ssl used site. If you want to use default adapterZend\Http\Client\Adapter\Socket you have to define sslcapath configuration option in order to allow PHP to validate the SSL certificate.
To avoid this I used the curl adapter instead.
$client = new Client();
$client->setUri($endPointUrl);
$options = array('put your options');
$client->setOptions($options);
$client->setAdapter('Zend\Http\Client\Adapter\Curl');
$response = $client->send();
Doc : http://framework.zend.com/manual/current/en/modules/zend.http.client.html
You need to set Http Client Options.
Here is the working setting:
// eko/FeedBundle and issue with ssl site -> https://github.com/eko/FeedBundle/issues/51
$httpClientOptions = array(
'adapter' => 'Zend\Http\Client\Adapter\Socket',
'persistent' => false,
'sslverifypeer' => false,
'sslallowselfsigned' => false,
'sslusecontext' => false,
'ssl' => array(
'verify_peer' => false,
'allow_self_signed' => true,
'capture_peer_cert' => true,
),
'useragent' => 'Feed Reader',
);
ZendFeedReader::setHttpClient(new ZendHttpClient(null, $httpClientOptions));
Here is the NOT working setting:
// eko/FeedBundle and issue with ssl site -> https://github.com/eko/FeedBundle/issues/51
$httpClientOptions = array(
'adapter' => 'Zend\Http\Client\Adapter\Socket',
'persistent' => false,
'sslverifypeer' => false,
'sslallowselfsigned' => true,
'sslusecontext' => true,
'ssl' => array(
'verify_peer' => false,
'allow_self_signed' => true,
'capture_peer_cert' => true,
),
'useragent' => 'Feed Reader',
);
ZendFeedReader::setHttpClient(new ZendHttpClient(null, $httpClientOptions));
Note: I have issue with symfony bundle eko/feedBundle that use Zend library so essentially it is the same for you.
this solution tested and proven to be working.

Sendgrid Unauthenticated senders not allowed error php, zf2

I have integrate Sendgrid for my Zend Framework 2 Application using STMP API and i have used Zend Transport for but I get a error
"Caught exception: Cannot receive from specified address : Unauthenticated senders not allowed"
$request = $this->getRequest();
//$form = new Add();
// $product = new Product();
$username = 'XXX';
$password ='XXXX';
if ($request->isXmlHttpRequest()){ // If it's ajax call
$email = $request->getPost('email_add');
$message = $request->getPost('message');
try{
$message = new Message();
$message->addTo('jainudeenf007#gmail.com')
->addFrom('fawazj#digitalglare.com.au')
->setSubject('Greetings and Salutations!')
->setBody("Sorry, I'm going to be late today!");
$transport = new SmtpTransport();
$options = new SmtpOptions(array(
'name' => 'sendgrid.com',
'host' => 'smtp.sendgrid.net',
'port' => 587, // Notice port change for TLS is 587
'connection_class' => 'smtp',
'connection_config' => array(
'auth' => 'login',
'username' => 'XXXXXX',
'password' => 'XXXXXX',
'ssl' => 'tls'
),
));
$transport->setOptions($options);
$transport->send($message);
exit;
}catch (\Exception $ex){
echo 'Caught exception: ', $ex->getMessage(), "\n";
exit;
}
}
Sendgrid has an api and this api is implemented by SlmMail (disclaimer: I am the author of SlmMail). Using that API is easier to use than using the old SMTP protocol.
I am not sure how to exactly configure the SMTP options, but previously we worked with the Google SMTP servers and it required this configuration:
'name' => 'gmail.com',
'host' => 'smtp.gmail.com',
'port' => 587,
'connection_class' => 'login',
'connection_config' => array(
'ssl' => 'tls',
'username' => $username,
'password' => $password,
),
This is slightly different than yours ("class" is "login", there is no "auth" option). Check also the documentation where all SMTP options are specified.
In addition to using the SimMail option, you can try using Zend's mail module as described in our documentation: http://sendgrid.com/docs/Integrate/Frameworks/zend.html
One other option is our Web API, for which we have a PHP library here: https://github.com/sendgrid/sendgrid-php
Try this
connection_class plain should work
use Zend\Mail\Transport\Smtp as SmtpTransport;
use Zend\Mail\Transport\SmtpOptions;
$transport = new SmtpTransport();
$options = new SmtpOptions(array(
'name' => $name,
'host' => $host,
'port' => 587,
'connection_class' => 'plain',
'connection_config' => array(
'username' => $username,
'password' => $password,
),
));
$transport->setOptions($options);
$transport->send($mail);

Resources