When I try to send an attachment using the SendGrid PHP library (https://github.com/sendgrid/sendgrid-php), the function fails (white screen). Removing the "setAttachment" line makes it work again.
Here is my code:
require "sendgrid-php/sendgrid-php.php";
function sendgrid() {
$recips = array("me#mydomain.ca");
$categories = array("test");
$sendgrid = new SendGrid("API key removed");
$email = new SendGrid\Email();
$email
->setSmtpapiTos($recips)
->setFrom('mailroom#mydomain.ca')
->setSubject('Testing Sendgrid')
->setText('Hello World! Testing...')
->setHtml('<strong>Hello World!</strong>')
->setCategories($categories)
->setAttachment('test.txt')
;
//$sendgrid->send($email);
$res = $sendgrid->send($email);
var_dump($res);
}
sendgrid();
As far as I can tell, I'm following the documentation, but I wonder if I haven't formatted the path to the file correctly. "Test.txt" is in the same directory as the file that contains the above code.
Can anyone offer any suggestions?
try this
->setAttachment(realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR.'test.txt');
this doesn't really belong here but as of April 17th 2019 SendGrid broke their postfix mechanism and enforced v3 PHP client without "proper" documentation. And I mean: nothing is properly documented so (since this post came up top of google when I typed in SendGrid - here goes)
so if you see this.. do not panic this post will help u
invalid authentication method - declined because you are using basic authentication with 2FA enabled. to fix, update to using an API key or disable 2FA and switch to using IP Access Management for security.
Some problems with the docs
SendGrids docs on v3 are (in my opinion)
declarative rather than informative (a functional declaration rather than technical information)
cripplingly wrong (wild goose chase of circular links)
out of date (with nothing to alert you)
missing essential components (so won't work out of the box with no hint as to why) ....
for example : (just a flavour) here we see "they" (SendGrid) simply took out \SendGrid\Email() and replaced it with \SendGrid\Mail\Mail() in their code base but didn't update their docs - so their posted examples will not work. - it's very minor as a change - but as written the callers are different and they never updated their examples.. with everything else they omitted it is making very hard work of a easy thing.
i.e. THIS EXAMPLE WORKS v3
$sendgrid = new SendGrid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
$email = new \SendGrid\Mail\Mail();
$email->setFrom("test#example.com", "Example User");
$email->setSubject("Sending with SendGrid is Fun");
$email->addTo("bigman#getme.com", "Example User");
$email->addContent(
"text/plain", "and easy to do anywhere, even with PHP"
);
$email->addContent(
"text/html", "<strong>and easy to do anywhere, even with PHP</strong>"
);
//optional (seems to be bullet proof, pdf, png, etc) to attach a file<START>
$att1 = new \SendGrid\Mail\Attachment();
$att1->setContent(file_get_contents("/path/to/some/test_attach.txt"));
$att1->setType("application/octet-stream");
$att1->setFilename(basename("/path/to/some/test_attach.txt"));
$att1->setDisposition("attachment");
$email->addAttachment($att1);
//optional to attach a file</END>
try {
$response = $sendgrid->send($email);
print $response->statusCode() . "\n";
print_r($response->headers());
print $response->body() . "\n";
}
catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}`
TO UPGRADE TO v3 SEND GRID PHP CLIENT without composer on PHP 5.6
if you're like me and hate composer (don't even get me started) THE GOOD NEWS IS you can get SendGrid to work so- just so you know .. almost everything "they" (SendGrid) direct you to online is going to struggle to help you
After April 17th 2019 SendGrid said you NEED to use v3 YOU WILL NEED PHP 5.6. (rightly or wrongly PHP 5.4 is the ceiling of redhat/centos at time of writing) and YOU CANNOT USE postfix anymore (despite them never specifically saying this nor labeling their postfix examples v2 max, i.e. disabled as of 17th April 2019)
So as of 17th April 2019
-> you have to use v3
-> you have to use the PHP client... (no postfix)
-> you have to upgrade to 5.6
-> you **DO NOT** have to use composer (but if you don't you need to pay attention, see below)
ALSO -> (IMPORTANT) you are stuck with the client or the curl at v3 (they don't simply say this) no postfix. forget it. also re: the Curl mechanism (while it does work with 5.4) carries a) no documentation on using attachments AND b) utilizes illegal json_encoding PHP cannot output ( PHP cannot give "{[{}]}" it's always "{"0":[{}]}")
but regardless not only MUST you use the SendGrid PHP client at 5.6 PHP (again no, server postfix option) you still need to know you need TWO projects: "php-http-client-master" and "sendgrid-php-master" (BOTH repos) and this is undocumented: then you need to do the following: and the /lib/loader.php in "sendgrid-php-master" needs these two lines adding at the end
require_once '/your/path/to/php-http-client-master/lib/Client.php';
require_once '/your/path/to/php-http-client-master/lib/Response.php';
you also need to add this (sadly more sloppiness from SendGrid)
require_once __DIR__ . '/mail/TypeException.php';
Incidentally I also edited sendgrid-php-master\sendgrid-php.php to this
<? php
require __DIR__ . '/lib/loader.php';
?>
theoretically adding composer would mean you could probably avoid all this but for some servers this is out of the question (implementing composer on a different branch of my PHP project took 3 weeks - I am not repeating this) since composer introduces a breaking change in the way PHP handles includes and class autoloading
PS: I have alerted SendGrid to all of this you may well find that this is cleared up pretty fast
Related
I have a php file that I use to send newsletters. Recently I moved to a new server and they use PEAR Mail instead of the default PHP mail to send mails and I had to update my script to function. But it's still not working. I get the TXT version not the HTML version.
If I manually enter the html codes inside the setHTMLBody() it works but when I replace it with my ob_start $output_string variable it doesn't work.
Here is my script;
ob_start();
include "URL/To/File.php";
$output_string = ob_get_contents();
ob_end_clean();
$headers['From'] = 'from#email.com';
$headers['Subject'] = 'Newsletter Subject';
require_once('Mail.php');
require_once('Mail/mime.php');
$message = new Mail_mime();
$message->setTXTBody("Your client doesn't support HTML.");
$message->setHTMLBody(''.$output_string.'');
$mail =& Mail::factory('mail');
$result = $mail->send('myemailaddress#gmail.com', $message->headers($headers), $message->get());
if (PEAR::isError($result)) {
echo("<span>" . $result->getMessage() . "</span>");
} else {
echo("<span style='color: #f7941c; font-weight: bold'>Congratulations!
Your mail has been sent successfully</span>");
}
how do I correctly input the line below correctly? It's not working as is right now.
$message->setHTMLBody(''.$output_string.'');
So I'm cold on this subject right now (working on mobile) though let's see if I can help you out. So I looked up the setHTMLBody function. It's a little fuzzy on the type that the expected parameters should be. In PHP you can get the type using gettype($example) (like console.log(typeof example); in JavaScript though PHP is generally more forgiving about types (calculating a number that has a string type will work in PHP, not JavaScript)).
The name of the function implies that it should make this part of the email HTML. Now of all the modules I've built on my web platform email has been the most challenging not because it's inherently complex though because it's very subjective. In example some servers might expect you to serve an <html> element, others a <body> element and others won't care if you omit it (and I'm not sure what if any specifications declare what is "proper" here). I've not intentionally worked with compressing data in emails (just output in web mail though it's technical context is lost at that point). Long story straight here: the client's user agent (browser, email application, etc) should be handling the compression, not you.
PHP ob stuff is a bit convoluted. I dislike the same function/method being used for both compression and being able to capture and do find/replace with the output before sending it to a client. I think you're using it for compression though you could also be using it to replace bits of code for whatever reason. In this case your best bet for troubleshooting (presuming that your ob should work, most likely for replacing bits of code) is to use the string and test it outside of this environment. When I test cron jobs I always test them in normal environments first (though keep in mind cron jobs run in a much more limited environment so for debugging there I just have print_r($_SERVER) send me information via email).
So I think your ob code is messing up the parser setHTMLBody() function. Break your code down until you have working bits and then add your necessary and increasingly complex bits to it until you hit a problem and then because you know exactly what you just added you'll be able to single out the issue much easier.
I'd need further clarification though I can edit this answer later. Let me know where you're at, I always check notifications even if it takes a day.
I have a few dozen tools that I use when I develop. I'm not sure if this tool will validate though it may help you somehow since you are working on email. https://www.mail-tester.com/ helped me address some issues related to email (it's not related to this issue).
I am using phpfickr and need to run it in CLI.
But when executing $ php getToken.php, but I'm not being able to getting authenticated. I have the $app_id and $secret.
Please, I am new to this and haven't found a correct solution.
The phpFlickr library you've linked to is very old.
Its most recent commit was on July 7, 2014, roughly 2.5 years ago.
It uses PHP 4 style constructors (named after the class), which have been deprecated in PHP 7 and will be removed in a future version of PHP.
It uses var keywords, another PHP 4 anachronism, which were briefly deprecated but then brought back as a semi-synonym of public.
If you really want to use this library it should be as simple as
<?php
require_once __DIR__ . '/phpflickr/phpFlickr.php';
// Make sure to fill in your API key and secret!
$flickr = new phpFlickr('your-api-key-goes-here', 'your-api-secret-goes-here');
The getToken.php file that you referenced does this. Perhaps you forgot to fill in your API key and secret?
Once you have your $flickr object you can use it to interact with Flickr's API. For example, you can do something like this to see titles of recently-posted public photos:
foreach ($flickr->photos_getRecent()['photos']['photo'] as $photo) {
echo $photo['title'] . "\n";
}
However, there are more modern options. rezzza/flickr, for example, is available on Packagist and has over 16K installs. It uses modern PHP features like namespaces, __construct() constructors, and visibility keywords. It also seems to have a more sane API, though that's subject to opinion.
If you are already using Composer you should be able to composer require rezzza/flickr, then proceed as its README suggests. If you're not using Composer, start. It is an important part of the modern PHP ecosystem.
Based on issue https://github.com/dan-coulter/phpflickr/issues/48 , adding
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
got me going.
This issue appears to be merged into master branch, but it does not exist.
I have a working PHP app that connects to Quickbooks online, loosely based on code from Pearce (thank you!). I'm using the Intuit PHPv3 SDK (version 2.0.4).
My setup code looks like:
<script type='text/javascript' src='https://appcenter.intuit.com/Content/IA/intuit.ipp.anywhere.js'></script>
<ipp:connectToIntuit></ipp:connectToIntuit>
and then, in Javascript:
intuit.ipp.anywhere.setup({
grantUrl: 'http://mywebsite.com/qbo/oauth'
});
This works fine, but I would like to add a Blue Dot Menu, which I assume gives the ability to disconnect the session and do other things. To do this, I know that the Javascript should really be saying:
intuit.ipp.anywhere.setup({
grantUrl: 'http://mywebsite.com/qbo/oauth',
menuProxy: 'http://mywebsite.com/qbo/blue-dot-menu
});
Trouble is, I have no idea what to put in the implementation code for the blue-dot-menu handler, and I've now spent quite a long time trying to figure this out from Intuit's documentation without success.
Any ideas appreciated!
The implementation of the Blue Dot menu is actually pretty simple -
Make a HTTP GET request to:
https://appcenter.intuit.com/api/v1/account/appmenu
That's OAuth authenticated. Print out the contents of what you get back to the page. Boom, done.
If you want an actual working example, use the open-source DevKit on GitHub - examples are here:
https://github.com/consolibyte/quickbooks-php
Specifically these examples:
https://github.com/consolibyte/quickbooks-php/tree/master/docs/partner_platform/example_app_ipp_v3
Which have a working example of the Blue Dot menu all ready to go for you, wrapped up in a nice OOP wrapper:
https://github.com/consolibyte/quickbooks-php/blob/master/docs/partner_platform/example_app_ipp_v3/menu.php
It's this simple:
<?php
require_once dirname(__FILE__) . '/config.php';
// Display the menu
die($IntuitAnywhere->widgetMenu($the_username, $the_tenant));
You can have a look at the following JAVA implementation.
https://github.com/IntuitDeveloperRelations/IPP_Sample_Code/blob/master/QuickbooksAPI/Java/Spring%20Application/QuickBooksAPI/src/main/java/com/intuit/controller/support/BluedotController.java
You need to make the following call in the PHP way(using the OAuth and Http libs).
final IAPlatformClient pClient = new IAPlatformClient();
final StringBuffer stringBuffer = new StringBuffer();
final List<String> menuList = pClient.getAppMenu(WebUtils.OAUTH_CONSUMER_KEY, WebUtils.OAUTH_CONSUMER_SECRET, accesstoken, accessstokensecret);
Other things are quite straight forward.
Hope it will be helpful.
Thanks
My question may be incorrect or even strange, but I'm really interested in such programming experience, and there is two reasons for that:
As a PHP developer I should do my work so I can't just switch to other programming language that easy; however, there is a lot of things that causes a lot of pain to write in PHP.
As a Python beginner I'm already a huge fan of this language, and there are things that can be done a lot easier and, IMHO, in more righteous way that PHP implementation suggests.
For example, I've been writing a broadcasting multiple-connection socket server in PHP, and anybody who has done similar thing would understand how many restrictions will cause such solution - detecting disconnect if client just closed browser is dreadful. Looking at broadcasting server implementations in Python makes me feel more comfortable.
Also, a think about applications that could work, say, in offline mode to gather user input and sending it to the processing server later, or stand-alone applications that are connected to a website, etc.
Searching the web is poor in this case. All I've found is PiP, but it was released too long ago and not documented well - there is probably a good reason for that.
I would be glad to hear any thoughts about this, because I understand that this idea is kind of crazy and looks like not a lot of people is concerned about it.
Some time ago I ran into a similar dilemma. The solution I found was use xml-rpc to expose python objects and methods so I can use them from php scripts. Here I left you the documentation of both.
Python: Python xml-rpc.
PHP: XML-PHP
EDIT: Adding example. The examples are the same that in the documentation. I just changed them a bit to make them shorter. In client.php I only call the div function from python server. Add the others your self.
server.py
from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
# Restrict to a particular path.
class RequestHandler(SimpleXMLRPCRequestHandler):
rpc_paths = ('/RPC2',)
# Create server
server = SimpleXMLRPCServer(("localhost", 8000),
requestHandler=RequestHandler)
server.register_introspection_functions()
# Register pow() function; this will use the value of
# pow.__name__ as the name, which is just 'pow'.
server.register_function(pow)
# Register a function under a different name
def adder_function(x,y):
return x + y
server.register_function(adder_function, 'add')
# Register an instance; all the methods of the instance are
# published as XML-RPC methods (in this case, just 'div').
class MyFuncs:
def div(self, x, y):
return x // y
server.register_instance(MyFuncs())
# Run the server's main loop
server.serve_forever()
client.php
<html>
<head><title>xmlrpc</title></head>
<body>
<h1>Php - Python - XMLRPC Demo</h1>
<?php
// Note that the path to xmlrpc.inc file is relative.
// to this file.
include("xmlrpc/lib/xmlrpc.inc");
// Params to python function 10 and 5.
// Build the message you want send.
// The message takes the function name and the params. See doc for details on how
// build params, is pretty easy.
$msg = new xmlrpcmsg( "div", array(new xmlrpcval(10, "int"), new xmlrpcval(5, "int")) );
// Build a XMLRCP - Client.
$client = new xmlrpc_client("/RPC2", "localhost", 8000);
// And send the message.
$response = $client->send($msg);
// From here all should look familier to you.
if(!$response->faultCode())
{
$v=$response->value();
echo "The result from div is" . htmlspecialchars($v->scalarval());
}
else
{
print "An error occurred: ";
print "Code: " . htmlspecialchars($r->faultCode())
. " Reason: '" . htmlspecialchars($r->faultString()) . "'</pre><br/>";
}
?>
<hr/>
</body>
</html>
I have a GTFS protocol buffer message (VehiclePosition.pb), and the corresponding protocol format (gtfs-realtime.proto), I would like to read the message in PHP alone (is that even possible?).
I looked at Google's python tutorial https://developers.google.com/protocol-buffers/docs/pythontutorial and encoding documentation https://developers.google.com/protocol-buffers/docs/encoding and https://github.com/maxious/ACTBus-ui/tree/master/lib/Protobuf-PHP, but I am having a really hard time conceptualizing what is going on. I think I understand that gtfs-realtime.php is a compiled instruction set of the encoding defined in gtfs-realtime.proto (please correct me if I am wrong), but I have no clue how to get it to decode VehiclePosition.pb. Also, what are the dependencies of gtfs-realtime.php (or the python equivalent for that matter)? Is there anything else I have to compile myself or anything that is not a simple php script if all I want to do is read VehiclePosition.pb?
Thanks.
edmonscommerce and Julian are on the right track.
However, I've gone down the same path and I've found that the PHP implementation of Protocol Buffers is cumbersome (especially in the case of NYCT's MTA feed).
Alternative Method (Command Line + JSON):
If you're comfortable with command line tools and JSON, I wrote a standalone tool that converts GTFS-realtime into simple JSON: https://github.com/harrytruong/gtfs_realtime_json
Just download (no install), and run: gtfs_realtime_json <feed_url>
Here's a sample JSON output.
To use this in PHP, just put gtfs_realtime_json in the same directory as your scripts, and run the following:
<?php
$json = exec('./gtfs_realtime_json "http://developer.mbta.com/lib/GTRTFS/Alerts/VehiclePositions.pb"');
$feed = json_decode($json, TRUE);
var_dump($feed);
You can use the official tool: https://developers.google.com/transit/gtfs-realtime/code-samples#php
It was released very recently. I've been using it for a few days and works like a charm.
I would assume something along the lines of this snippet:
<?php
require_once 'DrSlump\Protobuf.php';
use DrSlump\Protobuf;
$data = file_get_contents('data.pb');
$person = new Tutorial\Person($data);
echo $person->getName();
as taken from the man page: http://drslump.github.io/Protobuf-PHP/protobuf-php.3.html
Before that step, I think you need to generate your PHP classes using the CLI tool as described here: http://drslump.github.io/Protobuf-PHP/protoc-gen-php.1.html
so something along the lines of:
protoc-gen-php gtfs-realtime.proto
Sorry Harry Truong, I tried your executable but it returns always NULL.
What I am doing wrong?
Edit: The problem is that I have no permission to execute in my server. Thanks for your executable.