I am using Google App Engine and am trying to send email alerts with the Mail PHP API. I have defined a class with a public function but whenever I run it I get this error:
PHP Fatal error: Class 'Message' not found in...
PHP Code:
use \google\appengine\api\mail\Message;
class crawls {
public function check() {
try {
$message = new Message();
$message->setSender('Name <test#domain.com>');
$message->addTo($recipients);
$message->setSubject('Subject');
$message->setHTMLBody("<p>Message</p>");
$message->send();
} catch (InvalidArgumentException $e) {
$error = "Unable to send mail. $e";
}
}
}
Everything works when I move the code outside of the class, but I want it inside the class.
Inherit Message class :
Define namespace if required.
class crawls extends \google\appengine\api\mail\Message {
// your code
}
Try this may it works for you:
class crawls {
public function check() {
try {
$message = new \google\appengine\api\mail\Message();
$message->setSender('Name <test#domain.com>');
$message->addTo($recipients);
$message->setSubject('Subject');
$message->setHTMLBody("<p>Message</p>");
$message->send();
} catch (InvalidArgumentException $e) {
$error = "Unable to send mail. $e";
}
}
}
Hope it helps
Related
I configure json api in my suitecrm and now i want to add validation mandatory fields for some parameter please suggest me how to add validation and custom message.
I tried to add validation but can't get success is any idea how to configure validation message display
Use before_save logic hooks in that module in which you want to add validation then create you own method to check validation e.g. for checking pan number you can use pan regix then apiException
Hello try this one to your custom api controller
here`s my sample custom/application/Api/V8/Controller/CustomController.php
namespace Api\V8\Controller;
use Slim\Http\Request;
use Slim\Http\Response;
class CustomController extends BaseController
{
public function saveLeads(Request
$request, Response $response, array $args)
{
try {
$jsonResponse = $request->getParams();
$leadBean = \BeanFactory::newBean('Leads');
if(empty(jsonResponse['name'])
{
$resultMessage['Error'] = 'Please filled up the Name';
}else{
$leadBean->name = jsonResponse['name'];
$leadBean->save();
$resultMessage['Succes'] = Leads Has been created';
}
return $this->generateResponse($response, $resultMessage, 201);
} catch (\Exception $exception){
return $this->generateErrorResponse($response, $exception, 400);
}
}
I am trying to call a Google Cloud Endpoint API (developed on App Engine) via Google Apps Script. The endpoint is up and running, honestly I don't know which URL I should use but through Google Chrome Web Tools it looks like the URL is something like:
https://myapp.appspot.com/_ah/api/myendpointapi/v1/myEndPointMethod/
Along with API parameters directly included in the URL, separeted by slashes:
https://myapp.appspot.com/_ah/api/myendpointapi/v1/myEndPointMethod/param1value/param2value/...
Now, in order to call that API from Google App Script I am using the following code snippet:
function myFunction() {
var params =
{
"param1" : "param1value",
"param2" : "param2value",
};
var result = UrlFetchApp.fetch('https://myapp.appspot.com/_ah/api/myendpointapi/v1/myEndPointMethod/', params);
DocumentApp.getUi().alert(result);
}
However I always get a 404 error. If I have to be honest I don't even know if UrlFetchApp is the correct way of calling the API. I noticed this thread on StackOverflow but no one answered. What's the correct URL to use? Many thanks.
EDIT: Now I am trying with an API method which does not require any parameter. I found a way to call a specific URL (using method='get' as suggested by the answer below) but now I get a 401 error because it says I am not logged in. I believe I need to use some kind of OAuth parameter now. Any idea? I tryed using OAuthConfig but no luck with that as well :( From App Engine logs I can see the following error:
com.google.api.server.spi.auth.GoogleIdTokenUtils verifyToken: verifyToken: null
com.google.api.server.spi.auth.AppEngineAuthUtils getIdTokenEmail:
getCurrentUser: idToken=null
function myFunction() {
var result = UrlFetchApp.fetch('myurl', googleOAuth_());
result = result.getContentText();
}
function googleOAuth_() {
var SCOPE = 'https://www.googleapis.com/auth/drive';
var NAME = 'myAPIName';
var oAuthConfig = UrlFetchApp.addOAuthService(NAME);
oAuthConfig.setRequestTokenUrl('https://www.google.com/accounts/OAuthGetRequestToken?scope='+SCOPE);
oAuthConfig.setAuthorizationUrl('https://www.google.com/accounts/OAuthAuthorizeToken');
oAuthConfig.setAccessTokenUrl('https://www.google.com/accounts/OAuthGetAccessToken');
oAuthConfig.setConsumerKey('anonymous');
oAuthConfig.setConsumerSecret('anonymous');
return {oAuthServiceName:NAME, oAuthUseToken:'always'};
}
UrlFetchApp is the only way to call a Google Cloud Endpoints API at the moment. The second parameter to UrlFetchApp.fetch is a special key-value map of advanced options. To pass POST parameters, you need to do the following:
UrlFetchApp.fetch(url, {
method: 'post',
payload: {
"param1" : "param1value",
"param2" : "param2value",
}
});
I was fighting a similar (not the same) problem, when testing feasibility of a GCM backed by EndPoints server. Basically testing if it is possible to get the Google Spreadsheet Appscript to send notification to an Android device. Please bear with me, the following explanation may be a bit convoluted;
Starting with a standard 'Cloud Messaging for Android', backed by the 'App Engine Backend with Google Cloud Messaging', I managed to build a test system that would send messages between Android devices (Github here).
Here is a VERY sparse EndPoints server code that handles register / un-register Android devices, as well as reporting registered devices and sending a message to a list of registered devices.
WARNING: This is not a production quality code, it is stripped of any logging, error handling in order to keep it short.
#Api( name = "gcmEP", version = "v1",
namespace = #ApiNamespace(ownerDomain = "epgcm.example.com", ownerName = "epgcm.example.com", packagePath = "" )
)
public class GcmEP {
#ApiMethod(name = "registToken")
public void registToken(#Named("token") String token) {
if (ofy().load().type(TokenRec.class).filter("token", token).first().now() == null) {
ofy().save().entity(new TokenRec(token)).now();
}
}
#ApiMethod(name = "unregToken")
public void unregToken(#Named("token") String token) {
TokenRec record = ofy().load().type(TokenRec.class).filter("token", token).first().now();
if (record != null) {
ofy().delete().entity(record).now();
}
}
#ApiMethod(name = "listTokens")
public CollectionResponse<TokenRec> listTokens() {
return CollectionResponse.<TokenRec>builder().setItems(ofy().load().type(TokenRec.class).list()).build();
}
#ApiMethod(name = "sendMsg")
public void sendMsg(#Named("message") String message) throws IOException {
if (message != null && message.length() > 0) {
Sender sender = new Sender(System.getProperty("gcm.api.key"));
Message msg = new Message.Builder().addData("message", message).build();
for (TokenRec record : ofy().load().type(TokenRec.class).list()) {
Result result = sender.send(msg, record.getToken(), 4);
if (result.getMessageId() != null) {
// handle CanonicalRegistrationId
} else {
// handle errors, delete record
}
}
}
}
}
Android code for registration and message sending is shown here, even if it is not relevant.
GcmEP mRegSvc;
String mToken;
// register device on EndPoints backend server
private void registerMe() {
new Thread(new RegisterMe(this)).start();
}
private class RegisterMe implements Runnable {
Activity mAct;
public RegisterMe(Activity act) { mAct = act; }
public void run() {
String senderId = null;
if (mAct != null) try {
if (mRegSvc == null) {
mRegSvc = new GcmEP
.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null).setRootUrl(UT.ROOT_URL).build();
}
senderId = getString(R.string.gcm_defaultSenderId);
mToken = InstanceID.getInstance(mAct).getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
mRegSvc.registToken(mToken).execute();
GcmPubSub.getInstance(mAct).subscribe(mToken, "/topics/global", null); // subscribing to all 'topics' from 'mToken'
} catch (IOException e) { e.printStackTrace(); }
}
}
// send message to EndPoints backend server
new Thread(new Runnable() {
#Override
public void run() {
if (mRegSvc != null) try {
mRegSvc.sendMsg("hello").execute();
} catch (IOException e) { e.printStackTrace(); }
}
}).start();
// receive GCM message
public class GcmListenSvc extends GcmListenerService {
#Override
public void onMessageReceived(String senderId, Bundle data) {
Log.i("_X_", data.getString("message"));
}
}
What is relevant, thought, there is also an APIs Explorer created for the project, that can be used to send messages to your Android device from any browser.
If you use this Explorer, you can see the GET, POST requests for your EndPoints backend server, i.e.
list all registered devices:
GET https://epgcm.appspot.com/_ah/api/gcmEP/v1/tokenrec?fields=items
send a message to all registered devices:
POST https://epgcm.appspot.com/_ah/api/gcmEP/v1/sendMsg/Hello%20World!
Now, you can use this knowledge to send messages to your Android device from an AppScript code as shown:
Version 1: Get list of registered devices and send a GCM message to all of them (or a filtered set).
function sendMsg() {
var msg = 'test from CODE.GS';
var url = 'https://epgcm.appspot.com/_ah/api/gcmEP/v1/tokenrec?fields=items';
var params = { method : 'get'};
var response = UrlFetchApp.fetch(url, params);
var data = JSON.parse(response.getContentText());
var regIds = [];
for (i in data.items)
regIds.push(data.items[i].token);
var payload = JSON.stringify({
'registration_ids' : regIds,
'data' : { 'message' : msg }
});
var params = {
'contentType' : 'application/json',
'headers' : {'Authorization' : 'key=AIza............................'},
'method' : 'post',
'payload' : payload
};
url = 'https://android.googleapis.com/gcm/send';
UrlFetchApp.fetch(url, params);
}
This version relies on code from an old YouTube video, and I don't know if the call to 'android.googleapis.com' is still supported (but it works).
Version 2: Use the EndPoints's 'sendMsg' directly.
function sendMsg() {
var msg = 'test from CODE.GS';
var params = { method : 'post'};
var url = 'https://demoepgcm.appspot.com/_ah/api/gcmEP/v1/sendMsg/' + encodeURIComponent(msg.trim());
UrlFetchApp.fetch(url, params);
}
I have to admit I've never written a line of JavaScript code before, so it may not be up-to-par, but I made it work as a 'proof of concept'.
I would like to get feedback about this problem from people-who-know, since there is so little published info on this specific issue.
I want to create a custom exception. In this exception I want to make a constructor which take one string arguments and append in getMessage .How to accomplish this.
public class TimelineException extends Exception{
private String message;
public override String getMessage(){
return 'Not able to post to Timeline.getting response from Api : '+ message;
}
}
Main problem I am facing is when I use this:
public TimelineException(Sting x){
}
then its give me error
Save error: System exception constructor already defined: (String) GMirror.cls /Google Salesforce Integration/src/classes.
You do not need to implement something. Just create a your exception class which would extends salesforce Exception class.
public class CommonException extends Exception {}
then just use it as other exception classes
try {
throw new CommonException('Test Common Exception');
} catch(CommonException ex) {
System.debug(ex.getMessage());
}
console output:
09:18:55:059 USER_DEBUG [4]|DEBUG|Test Common Exception
You can use something like this in your controller:
try
{
'content of what you tring to do'
}
catch(Exception e)
{
system.debug(e.getStackTraceString());
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'special friendly message to user'));
}
then in the visualForce page you write apex:messages/ where you want the message to be displayed
I'm getting [310] Too many redirects errors on heroku, when my cake app tries to redirect to a secure connection after forcing it with SecurityComponent::requireSecure().
public function beforeFilter() {
$this->Security->blackHoleCallback = '_blackholeCallback';
$this->Security->requireSecure('login', 'register');
}
// ...
public function _blackholeCallback($type) {
if ($type == 'secure') {
$this->redirect('https://' . env('SERVER_NAME') . $this->here);
}
}
The problem was that CakePHP and heroku handle their secure connections differently.
Cake's checking for the environmental variable 'HTTPS' to be true or false.
heroku doesn't provide this env, instead they're sending the header 'X-Forwarded-Proto' with a 'https' value.
You have to add a new (or overwrite the old 'ssl') detector and check for this header.
I did it like this:
class AppController extends Controller {
public function beforeFilter() {
$this->request->addDetector('ssl', array('callback' => function() {
return CakeRequest::header('X-Forwarded-Proto') == 'https';
}));
// ...
}
}
Hope i could help everyone who's having this issue after me. it got me several hours to figure this out.
I wanna have a different layout for the page not found 404 page. How can i set a different layout for that page?
Savant from the IRC helped me out and he suggest in using beforeRender(){} in the app_controller
// Before Render
function beforeRender() {
if($this->name == 'CakeError') {
//$this->layout = 'error';
}
}
CakeError is a catchAll for errors :D
In CakePHP 2.2.2 I changed the ExceptionRenderer in core.php with my own, like this:
app/Config/core.php:
Configure::write('Exception', array(
'handler' => 'ErrorHandler::handleException',
'renderer' => 'MyExceptionRenderer', // this is ExceptionRenderer by default
'log' => true
));
app/Lib/Error/MyExceptionRenderer.php:
App::uses('ExceptionRenderer', 'Error');
class MyExceptionRenderer extends ExceptionRenderer {
protected function _outputMessage($template) {
$this->controller->layout = 'error';
parent::_outputMessage($template);
}
}
Just you need to make layout changes in your error400.ctp file under /app/View/Errors/error400.ctp
Open that file and set layout by
<?php $this->layout=''; //set your layout here ?>
better to create an error.php file in your app folder
class AppError extends ErrorHandler {
function error404($params) {
$this->controller->layout = 'error';
parent::error404($params);
}
}
so you can avoid the if-testing at EVERY page render that savants' solution introduces
My solution for CakePHP 2.3
Change the ExceptionRenderer in core.php to use your own renderer.
app/Config/core.php:
Configure::write('Exception', array(
'handler' => 'ErrorHandler::handleException',
'renderer' => 'MyExceptionRenderer',
'log' => true
));
app/Lib/Error/MyExceptionRenderer.php:
App::uses('ExceptionRenderer', 'Error');
class MyExceptionRenderer extends ExceptionRenderer
{
/**
* Overrided, to always use a bare controller.
*
* #param Exception $exception The exception to get a controller for.
* #return Controller
*/
protected function _getController($exception) {
if (!$request = Router::getRequest(true)) {
$request = new CakeRequest();
}
$response = new CakeResponse(array('charset' => Configure::read('App.encoding')));
$controller = new Controller($request, $response);
$controller->viewPath = 'Errors';
$controller->layout = 'error';
return $controller;
}
}
The advantage to this approach is that it ensures any exceptions thrown from AppController don't cause an endless loop when rendering the exception. Forces a basic rendering of the exception message every time.
This simplest way I know of is to create this function in your AppController:
function appError($method, $messages)
{
}
You can then do whatever you want with the error, display it however you like, or not display it at all, send an email etc.. (I'm not sure if this method if still valid.)
There is also an option of creating app_error.php in your app root, with class AppError extends ErrorHandler in it, which enables you to override all kinds of errors. But I haven't done this yet, so I can't tell you more about it.
See cake/libs/error.php and cake/libs/object.php and of course The Book for more info.
Edit: Forgot to mention, once you caught the error, there's nothing preventing you to - for example - store the error in session, redirect to your "error handling controller", and then display it in your controller however you want.