function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
DRSnyderDRSnyder 

Messaging.sendEmail Not Sending Email

I'm having a problem sending e-mail from an APEX controller extension. Here's the code followed by the results from the debug log.

 

public class leadExtension {

public leadExtension(ApexPages.StandardController controller) {
this.lead = (Lead)controller.getRecord();

// Create a new single email message object
// that will send out a single email.
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

// Strings to hold the email addresses to which you are sending the email.
String[] toAddresses = new String[] {'********@hsabank.com'};

// Assign the addresses for the To list to the mail object.
mail.setToAddresses(toAddresses);

// Specify the address used when the recipients reply to the email.
mail.setReplyTo('********@hsabank.com');

// Specify the name used as the display name.
mail.setSenderDisplayName('HSA Bank');

// Specify the subject line for your email address.
mail.setSubject('New Contact Request: ' + lead.FirstName);

// Set to True if you want to BCC yourself on the email.
mail.setBccSender(false);

// Optionally append the salesforce.com email signature to the email.
// The email address of the user executing the Apex Code will be used.
mail.setUseSignature(false);

// Specify the text content of the email.
mail.setPlainTextBody('Please add this new contact...');

mail.setHtmlBody('Please add this new contact...');

// Send the email you have created.
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
}

private final Lead lead;
}
<apex:page tabStyle="Lead" standardController="Lead" extensions="leadExtension" >
    <apex:form >
    <apex:sectionHeader title="New Contact Request" />
    <h1>Notice Sent</h1>
    <p>
        Congratulations, your request to add a new Contact has been submitted. 
    </p>
    <apex:outputField title="First Name:" value="{!Lead.FirstName}"/>
    </apex:form>
</apex:page>
Element thePage called method {!checkManageability} returned type PageReference: none
***Begining Page Log for /apex/New_Contact_Request
20090801203603.582:Class.leadExtension.<init>: line 38, column 42: Single email queued for send (pending commit) : replyTo: ********@hsabank.com, subject: New Contact Request: Randy, senderDisplayName: HSA Bank, bccSender: false, saveAsActivity: true, useSignature: false, toAddresses: [********@hsabank.com], plainTextBody: Please add this new contact..., htmlBody: Please add this new contact...,
20090801203603.582:Class.leadExtension.<init>: line 39, column 9: Email result true
20090801203603.582:External entry point: returning from end of method public leadExtension<Constructor>(ApexPages.StandardController) in 38 ms
Cumulative profiling information:

No profiling information for SOQL operations.

No profiling information for SOSL operations.

No profiling information for DML operations.

1 most expensive method invocations:
Class.leadExtension: line 3, column 12: public leadExtension<Constructor>(ApexPages.StandardController): executed 1 time in 38 ms


***Ending Page Log for /apex/New_Contact_Request?id=00Q8000000SRUBJ&core.apexpages.devmode.url=1&scontrolCaching=1

 

I suppose I should first point out that I'm fairly new to Salesforce, and this is the first class I've tried to develop on my own. So, please be gentle with me! :smileywink: 

 

Based on what I can see, everything appears to be working fine, and the associated Visualforce page displays without error. The code is running inside leadExtension constructor. The problem is that the e-mail never arrives. I've got a couple different Developer Edition orgs, and I've tied this code in both. I get the same result.

 

I get other e-mails from Salesforce, like the security token re-set, e-mail change confirmation, etc. So, I know mail is getting through from them.

 

Also, I checked the Email Logs, and it doesn't appear to show any e-mails being sent at the time that I tried to send them.

 

So, I'm a little stumped. Can somebody point me in the right direction.

Message Edited by DRSnyder on 08-01-2009 02:08 PM
Message Edited by DRSnyder on 08-03-2009 11:15 AM
Best Answer chosen by Admin (Salesforce Developers) 
DRSnyderDRSnyder
OK, I figured this out... If I took the e-mail code out of the constructor and placed the code in a separate method. Then, instead of calling the code immediately, had the end-user click a button I could get e-mails to go. It's not exactly what I was originally trying to do, but actually works better for the business scenario I was trying to solve.

All Answers

paul-lmipaul-lmi

you have no error handling at all in your code.  try this, and run the VF page with the System Log applet open.

 

also, it'd be helpful if you posted the code to the page.  from what i can see, you're never actually calling the code.  you should be wrapping your email sending logic in a method that you can call from the page, ie, a PageReference.

 

here's an example of an existing working VF email sender.  don't mind the extra code, i didn't feel like stripping everything out for this simple example.  here's the basics

 

  1. page contains an apex:commandButton that calls "{!sendEmail}" as it's action attibute
  2. controller's sendEmail method actually sends the email

 

 

<apex:page id="page" controller="RescueAPICon" title="LogMeIn Rescue PIN Code" showHeader="false" sidebar="false"> <body> <table width="420" border="0" cellpadding="0" cellspacing="0" style="border-top: 5px solid black; border-bottom: 5px solid black; border-left: 2px solid black; border-right: 2px solid black"> <tr> <td> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr> <td valign="top" style="width: 150px; text-align: left"> <table cellpadding="0" cellspacing="0" width="150"> <tr> <td valign="top" style="padding-top: 6px; padding-left: 18px; width: 155px; height: 40px"> <apex:image value="{!URLFOR($Resource.Rescue_Resources, 'images/rescue_pwdby_new.gif')}" alt="Powered by LogMeIn Rescue" title="Powered by LogMeIn Rescue" /></td> <td style="width: 25px" valign="top"><apex:image value="{!URLFOR($Resource.Rescue_Resources, 'images/tri.gif')}" /> </td> </tr> </table> </td> <td align="right" valign="top" style="width: 100%"> <table cellpadding="0" cellspacing="0" style="height: 25px; background-color: Black;" width="100%" > <tr> <td style="padding-left: 3px; padding-right: 3px; width: 100%" align="left"> </td> <td style="padding-left: 3px;" align="right"> <c:Rescue_AjaxWorkingIcon /> </td> </tr> </table> </td> </tr> </table> <table cellpadding="0" cellspacing="0" width="100%"> <tr> <td style="padding-left: 20px; padding-right: 20px; padding-bottom: 20px"> <apex:form id="form"> <table> <tr> <td id="emaillabelspan" ><apex:outputLabel id="emaillabel" styleClass="label" value="Customer Email" /></td> <td id="emailtextspan" ><apex:inputText id="email" value="{!email}" styleClass="textbox" title="Customer Email" tabindex="1" /></td> </tr> <tr> <td id="bodylabelspan" ><apex:outputLabel id="bodylabel" styleClass="label" value="Email Text" /></td> <td id="bodyspan" ><apex:inputTextArea id="emailbody" value="{!EmailBody}" styleClass="textbox" title="Email Text" tabindex="2" rows="6" /></td> </tr> <tr> <td colspan="2" align="right" > <apex:commandButton styleClass="cmdbutton" id="emailpin" value="Email PIN" action="{!sendEmail}" reRender="messages" tabIndex="3" status="status"/> </td> </tr> </table> </apex:form> </td> </tr> <tr> <td> <div class="messageblock"><apex:pageMessages id="messages" /> </div> </td> </tr> </table> <table cellpadding="0" cellspacing="0" border="0" style="width: 100%; height: 20px; background-color: black; color: white"> <tr> <td style="padding-left: 20px; padding-bottom: 2px; white-space: nowrap; font-size: 8pt" valign="bottom"> <apex:outputLabel style="color: white;" value="Copyright &copy; 2005-2009 LogMeIn, Inc. All rights reserved." escape="false"/> </td> </tr> </table> </td> </tr> </table> <script type="text/javascript"> document.getElementById("page:form:email").focus(); </script> </body> </apex:page>

 

 The button calls the controller's "sendEmail" method, which is doing the actual work.

 

controller

 

 

public with sharing class RescueAPICon { Final String apiurl = 'https://secure.logmeinrescue.com/api/'; String email; String pwd; String authcode; String logincookieheader; String body; String pin; String caseid = ApexPages.currentPage().getParameters().get('caseid'); Boolean showPin = false; String emailBody = 'Hi,\n\n' + 'Please click the following link to start your support session.\n\n'; String pinLink = 'https://secure.logmeinrescue.com/R?i=2&Code='; /* handle the email input */ Public String getEmail(){ return email; } Public void setEmail(string e){ this.email = e; } /* handle the user password input */ Public String getPwd(){ return pwd; } Public void setPwd(string p){ this.pwd = p; } /* handle the PIN code value */ Public String getPin(){ return pin; } Public void setPin(string p){ this.pin = p; } /* method to generate authcodeurl */ Public String constructauthcodeurl(){ String authCodeUrl = apiurl + 'requestAuthCode.aspx'; return authCodeUrl; } /* handle the showPin flag */ Public boolean getShowPin(){ return showPin; } /* build the request for the authcode request */ Public HttpRequest authCodeReq(){ String url = constructauthcodeurl(); HttpRequest req = new HttpRequest(); req.setEndpoint(url); req.setMethod('POST'); req.setBody('email=' + EncodingUtil.urlEncode(email, 'UTF-8') + '&pwd=' + EncodingUtil.urlEncode(pwd, 'UTF-8')); req.SetHeader('Content-Length', String.valueOf(req.getBody().length())); System.Debug(LoggingLevel.DEBUG, 'Request object: ' + req); return req; } /* method to generate pincodeurl */ Public String constructpincodeurl(){ String pinUrl = apiurl + 'requestPINCode.aspx'; return pinUrl; } /* build the request for the pincode request */ Public HttpRequest pinCodeReq(){ String url = constructpincodeurl(); System.debug(LoggingLevel.INFO, 'URL endpoint is: ' + url); HttpRequest req = new HttpRequest(); req.setEndpoint(url); System.debug('Req after endpoint: ' + req); req.setMethod('POST'); System.debug('Req after method: ' + req); System.debug('Authcode: ' + authcode); String reqBody = 'authcode=' + authcode + '&notechconsole=true' + '&tracking0=' + caseid; System.debug(LoggingLevel.Info, 'Request body: ' + reqBody); req.setBody(reqBody); req.SetHeader('Content-Length', String.valueOf(req.getBody().length())); System.Debug(LoggingLevel.DEBUG, 'Request object: ' + req); return req; } /* send an http request */ Public HttpResponse httpRes(HttpRequest req){ try{ Http http = new Http(); HttpResponse res = http.send(req); system.debug(LoggingLevel.INFO, 'Response: ' + res.getBody()); return res; }catch(exception e){ system.debug(LoggingLevel.ERROR, 'Error sending HTTP request.'); system.debug(e); ApexPages.addMessages(e); return null; } } /* method to generate an authcode and store it in the RescueAuthCode__c field of the current user */ Public void generateAuthCode(){ /* reset authcode in case they clicked more than once */ authcode = ''; try{ HttpResponse authRes = httpRes(authCodeReq()); If(authRes != null && authRes.toString() != ''){ body = authRes.getBody(); System.debug(LoggingLevel.INFO, 'Response Body: ' + body); body = authRes.getBody(); System.debug(LoggingLevel.INFO, 'Response Body: ' + body); if (body.contains('OK')){ /* login was OK */ authcode = body.split(':')[1]; } else { /* login failed */ system.debug(LoggingLevel.ERROR, 'Login failed, Please check your LogMeIn Rescue email and password.'); ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.ERROR, 'Login failed, Please check your LogMeIn Rescue email and password.'); ApexPages.addMessage(msg); } } } catch(exception e){ system.debug(LoggingLevel.ERROR, 'AuthCode generating failed.'); system.debug(e); ApexPages.addMessages(e); } } Public void setAuthCodeForUser(string a){ /* get the user object to manipulate */ try{ User usr = new User(); usr = Database.query('select id, RescueAuthCode__c from User where id = \'' + UserInfo.getUserId() + '\''); usr.RescueAuthCode__c = a; update usr; system.debug(LoggingLevel.INFO, 'Successfully linked accounts.'); ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.INFO, 'Successfully linked accounts. \n <a href="/apex/RescueRequestPINCode">Click here to generate a PIN Code.</a>'); ApexPages.addMessage(msg); } catch(exception e){ system.debug(LoggingLevel.ERROR, 'Setting User RescueAuthCode__c failed'); system.debug(e); ApexPages.addMessages(e); } } /* get the current user's authcode */ Public String getStoredAuthCode(){ User usr = new User(); usr = Database.query('select id, RescueAuthCode__c from User where id = \'' + UserInfo.getUserId() + '\''); return usr.RescueAuthCode__c; } /* handle the emailBody */ Public string getEmailBody(){ String text = emailBody; text += pinLink; text += getPinCodeFromUrlParam(); return text; } Public void setEmailBody(string s){this.emailBody = s; } /* this method enables the sendEmail form to parse and use the pin code */ Public string getPinCodeFromUrlParam(){ String pin = ApexPages.CurrentPage().getParameters().get('pin'); return pin; } /* provide click action to link Rescue AuthCode to Salesforce account */ Public PageReference linkAccounts(){ generateAuthCode(); if(authcode != '' && authcode != null){ setAuthCodeForUser(authcode); } return null; } /* this action will remove the AuthCode from the User object */ Public PageReference clearAuthCode(){ User usr = new User(); usr = Database.query('select id, RescueAuthCode__c from User where id = \'' + UserInfo.getUserId() + '\''); usr.RescueAuthCode__c = ''; update usr; system.debug(LoggingLevel.INFO, 'Accounts have been unlinked.'); ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.INFO, 'Accounts have been unlinked.'); ApexPages.addMessage(msg); return null; } /* this method will submit the request to generate a PIN code */ Public PageReference requestPin(){ authcode = getStoredAuthCode(); if (authcode != '' && authcode != null){ /* submit the PIN request */ pin = ''; try{ System.Debug(pinCodeReq()); HttpResponse pinRes = httpRes(pinCodeReq()); If(pinRes != null && pinRes.toString() != ''){ body = pinRes.getBody(); System.debug(LoggingLevel.INFO, 'Response Body: ' + body); if (body.contains('OK')){ /* login was OK */ pin = body.split(':')[1]; showPin = true; } else { /* login failed */ system.debug(LoggingLevel.ERROR, 'Request failed, Please check your LogMeIn Rescue email and password.'); ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.ERROR, 'Login failed, Please check your LogMeIn Rescue email and password.'); ApexPages.addMessage(msg); } } } catch(exception e){ system.debug(LoggingLevel.ERROR, 'Error getting PIN Code.'); system.debug(e); ApexPages.addMessages(e); return null; } return null; } else { /* redirect user to the link account page */ PageReference ref = new PageReference('/apex/RescueGenerateAuthCode'); ref.setRedirect(true); return ref; } } /* this method simply redirects to the PIN email form */ Public PageReference emailPin(){ PageReference ref = new PageReference('/apex/RescueEmailPIN' + '?pin=' + getPin()); ref.setRedirect(true); return ref; } /* this method parses the info in the sendEmail form and send the email on behalf of the logged in user */ Public PageReference sendEmail(){ try{ Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); mail.setPlainTextBody(getEmailBody()); //mail.setHtmlBody(emailBody); mail.setToAddresses(new String[]{getEmail()}); mail.setSubject('Your ' + UserInfo.getOrganizationName() + ' PIN code'); mail.setUseSignature(true); /*finally, send the email */ Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail }); system.debug(LoggingLevel.INFO, 'Email sent to: ' + getEmail()); ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.INFO, 'Email sent to: ' + getEmail()); ApexPages.addMessage(msg); return null; }catch (exception e){ system.debug(LoggingLevel.ERROR, 'Error sending email. ' + e); ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.ERROR, 'Error sending email. Please enter a valid email address.'); ApexPages.addMessage(msg); return null; } } }

 

 

 

 

 

DRSnyderDRSnyder

I added the VF page to my original post.

 

The code is actually running inside the leadExtension constructor. If you look at the log, it shows that an e-mail is queued for sending. But, I never receive that e-mail.

 

I'll add in the error handling. I had a little bit, but stripped it out before I posted the message, as it wasn't telling me anything.

JohannesBorrmanJohannesBorrman

EDIT:

 

it must have something to do with extending the standard controller.  i rewrote my extension completely (which i reused from a similar "view-only" page) and it worked ... the main purpose of my page is displaying related case items and doing special actions with them (from a pageblocktable) -ö- 

 

 

I'm wondering how this progressed ... can you tell me already? Have some strange behaviour related to this errormsg too and can't figure out why.

 

regards, Johannes

Message Edited by JohannesBorrman on 08-17-2009 08:57 AM
DRSnyderDRSnyder
OK, I figured this out... If I took the e-mail code out of the constructor and placed the code in a separate method. Then, instead of calling the code immediately, had the end-user click a button I could get e-mails to go. It's not exactly what I was originally trying to do, but actually works better for the business scenario I was trying to solve.
This was selected as the best answer
William212121William212121

I'm having the same issue, but I need to get it working without
using a button. Have you found out how to send successfully without requiring a
button click?

brianhksbrianhks

You can do this by adding an action to your apex:page tag.  In my case I added action="{!sendEmail}" and then I had an method on my controller extentions called

 

public PageReference sendEmail()

 

sendEmail just returns null.

BBeairdBBeaird

I know this thread is old, but I made a crazy discovery this morning.

 

You can still have the email action called from the constructor WITHOUT a button. You do need to have an "action" tag on the page that refers to some controller method, but that method doesn't have to be the email method! In fact, that method doesn't have to do anything at all and could just be a blank void method.

 

But as soon as your page has that action tag, you can send e-mail straight from the constructor, and it goes through. It's like that tag "enables" email to be sent straight from the page constructor, even if the actual method being called from it isn't the piece sending the e-mail. So odd, but at least it's a nice workaround to be able to send e-mails when I need to.

 

This was so confusing because without the action tag, the debug logs would say the e-mail sent fine but I would never actually receive it.

 

**Update: it looks like you're still out of luck if you want to do this from a controller that's referenced from a visualforce component. Components do not support that action tag, so the e-mail still just doesn't get sent out. I have a case with Salesforce - will see what they say about it.