Sending Sitecore emails through Gmail - gmail

I'm trying to make Sitecore send messages through a gmail-account but it wont work.
This is my settings in web.config:
<setting name="MailServer" value="smtp.gmail.com" />
<!-- MAIL SERVER USER
If the SMTP server requires login, enter the user name in this setting
-->
<setting name="MailServerUserName" value="adress#gmail.com" />
<!-- MAIL SERVER PASSWORD
If the SMTP server requires login, enter the password in this setting
-->
<setting name="MailServerPassword" value="secret" />
<!-- MAIL SERVER PORT
If the SMTP server requires a custom port number, enter the value in this setting.
The default value is: 25
-->
<setting name="MailServerPort" value="587" />
And this is the error from the log:
6068 09:14:57 ERROR Failed to send analytics report
Exception: System.Net.Mail.SmtpException
Message: The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.0 Must issue a STARTTLS command first. u9sm3416817eeh.17
Source: System
at System.Net.Mail.MailCommand.CheckResponse(SmtpStatusCode statusCode, String response)
at System.Net.Mail.MailCommand.Send(SmtpConnection conn, Byte[] command, String from)
at System.Net.Mail.SmtpTransport.SendMail(MailAddress sender, MailAddressCollection recipients, String deliveryNotify, SmtpFailedRecipientException& exception)
at System.Net.Mail.SmtpClient.Send(MailMessage message)
at Sitecore.MainUtil.SendMail(MailMessage message)
at Sitecore.Analytics.Reports.ReportMailer.Mail(String exportedReportFileName, IEnumerable`1 recipients, String reportTitle, Boolean embedFile, Boolean deleteFile)
I know that it has something to do with gmail requiring some kind of secure connection but how do I make Sitecore provide this?

In 8.2 update 4 (don't know about previous updates/releases) there's a special setting for that:
<setting name="MailServerUseSsl" value="true" />

Message: The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.0 Must issue a STARTTLS command first.
gmail requires TLS connection. Can try looking into stunnel.
Anyways, serverfault or superuser.com is probably more appropriate.

The SendMail function in Sitecore.MainUtil does not have an option to set SmtpClient.EnableSsl to True. For now, it looks like you will need to find another SMTP server to use.
You may want to log this as a feature request with Sitecore.

I am successfully connect to GMAIL using Email Campaign module which has the STARTTLS feature.
Here are my settings:
<!--Set it to "true" if you want use the SMTP settings below. You should purchase the right of using the "UseLocalMTA" setting first.-->
<setting name="UseLocalMTA" value="true" />
<setting name="SMTP.Server" value="smtp.gmail.com" />
<setting name="SMTP.Port" value="587" />
<setting name="SMTP.LoginDomain" value="" />
<setting name="SMTP.UserName" value="user#gmail.com" />
<setting name="SMTP.Password" value="12345" />
<setting name="SMTP.AuthMethod" value="PLAIN" />
<setting name="SMTP.StartTLS" value="true" />

Related

FABRIC_E_INVALID_ADDRESS when contacting service fabric stateless service through remote proxy

I am getting a "FABRIC_E_INVALID_ADDRESS" 400 Bad Request when contacting my stateless service externally.
I have set up the reverse proxy exactly as it says in this article: https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-reverseproxy
I am contacting the service the same way it explains to in the documentation, with:
http://clustername.com:19008/MyApp/MyService
I am fairly confident the reverse proxy is working as intended, because the port 19008 returns a response from service fabric. Also:
If I strip MyService from the URL, I get a 404 SERVICE_DOES_NOT_EXIST
If I change the service name, I get a 404 SERVICE_DOES_NOT_EXIST
If I use another port, I get a timeout.
So it sees that the service exists, but returns the invalid address 400 error.
Are there any sort of diagnostics I can leverage? The main issue with this problem is all I have to go on is 400 FABRIC_E_INVALID_ADDRESS, which produces no google results other than a list of error codes with no descriptions from MSDN. There is nothing else in the response headers.
I had the same error but it begun to work when I added the UriScheme and Protocol attributes to the Endpoint in the ServiceManifest.xml Endpoints sections:
<Endpoint Name="Test1TypeEndpoint" UriScheme="http" Protocol="http" />
as I am deploying using Guest Containers, it will not work until you also add a Policiy in the ServiceManifestImport section of the ApplicationManifest.xml stating the port exposed by the docker container:
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="Test1Pkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
<Policies>
<ContainerHostPolicies CodePackageRef="Code">
<PortBinding ContainerPort="80" EndpointRef="Test1TypeEndpoint" />
</ContainerHostPolicies>
</Policies>
</ServiceManifestImport>
The CodePackageRef attribute must match the CodePackage Name of the ServiceManifest.xml:
<CodePackage Name="Code" Version="1.0.0">

ELMAH - Get SMTP credentials from Azure Application Settings

I've got an Azure Web App using ELMAH to log unhandled exceptions.
When I first deployed it, the web.config had the full SMTP setup defined in it, and ELMAH emailed exceptions:
<system.net>
<mailSettings>
<smtp from="me#mydomain.com">
<network host="smtp.mailprovider.com"
port="123"
userName="myUserName"
password="p#ssw0rd" />
</stmp>
</mailSettings>
</system.net>
The username and password have since been removed from the web.config, and they're now stored as application settings, configured through the Azure Portal.
Most of the emails I send still work fine, as the email code can access these application settings and use them when instantiating the SmtpClient, e.g.:
var userName = WebConfigurationManager.AppSettings["smtp.userName"];
var password = WebConfigurationManager.AppSettings["smtp.password"];
var credentials = new NetworkCredential(userName, password);
using (var smtpClient = new SmtpClient { Credentials = credentials })
{
await smtpClient.SendMailAsync(mailMessage);
}
What's the best way to get ELMAH to use the credentials stored in the application settings?
Options I can see:
There is a page on the wiki explaining how to use ELMAH's ErrorTweetModule to do an HTTP form post with the error details to any URL. The controller receiving the post could then use the stored credentials to email the details on.
The WebBase has a link to an article suggesting you can send emails directly to the recipient's SMTP server without authentication, but it says this may not work if you have DomainKeys set up, which I do.
This answer links to an article about intercepting the Mailing event, to customise the message.
I ended up creating a custom version of Elmah's ErrorMailModule, derived from the standard one, but overriding the SendMail method, based on some advice from Atif Aziz in a discussion on Google Groups.
The only changes required were to create the new module, and switch the Web.Config to use the custom module instead of the standard one.
Module
using System;
using System.Net.Mail;
namespace Test
{
public class ErrorMailModule : Elmah.ErrorMailModule
{
protected override void SendMail(MailMessage mail)
{
if (mail == null) throw new ArgumentNullException(nameof(mail));
// do what you want with the mail
// (in my case this fires up the email service, which
// gets the credentials from the Azure settings)
}
}
}
Web Config Changes
All that's required is to change the two occurrences of Elmah.ErrorLogModule, Elmah to your own module, in this case Test.ErrorMailModule.
So, instead of this...
<system.web>
<httpModules>
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
</httpModules>
</system.web>
<system.webServer>
<modules>
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
</modules>
</system.webServer>
...you should now have this:
<system.web>
<httpModules>
<add name="ErrorMail" type="Test.ErrorMailModule" />
</httpModules>
</system.web>
<system.webServer>
<modules>
<add name="ErrorMail" type="Test.ErrorMailModule" preCondition="managedHandler" />
</modules>
</system.webServer>
You will still need the errorMail section, as Elmah is still responsible for creating the email. Mine looks like this:
<elmah>
<errorMail from="user#domain.com" to="user#domain.com" subject="Custom Email Module"/>
</elmah>
Creating a HTTP request could work, but that should be the solution if everything else doesn't work IMO. Intercepting the Mailing event doesn't work, since you do not have access to the SmtpClient with the credentials in that event.
I've looked at different ways to update the SMTP settings from code. At first I though that I could just get a reference to the smtp section and update the properties, since they all have setter. But the code throw a configuration exception on runtime.
From what I can find, the only way to update the username and password in smtp section, is to read the web.config, update it and write the new version. Here's an example of writing updates to web.config:
var configuration = WebConfigurationManager.OpenWebConfiguration("~");
var section = configuration.GetSection("system.net/mailSettings/smtp") as SmtpSection;
section.Network.UserName = ConfigurationManager.AppSettings["myusername"];
section.Network.Password = ConfigurationManager.AppSettings["mypassword"];
configuration.Save();
The code actually updates the web.config. The code can be run at startup, but that would modify your web.config file locally as well. Another approach would be to run the code as part of a post deployment task with Azure.

Optimal settings for serving images with ImageProcessor AzureBlobCache

I've been trying to understand the issues https://github.com/JimBobSquarePants/ImageProcessor/issues/161 and https://github.com/JimBobSquarePants/ImageProcessor/issues/178 discusses here.
I have an environment where i have my regular site on http://example.com and i have a separate site for imageprocessor served from http://d.example.com.
Then i have the Azure blob cache setup like this.
<setting key="CachedStorageAccount" value="DefaultEndpointsProtocol=https;AccountName=***********;AccountKey=************" />
<setting key="CachedBlobContainer" value="imgcache" />
<setting key="UseCachedContainerInUrl" value="false" />
<setting key="CachedCDNRoot" value="https://imgcdn.azureedge.net/" />
<setting key="SourceStorageAccount" value="DefaultEndpointsProtocol=https;AccountName=**********;AccountKey=***************" />
<setting key="SourceBlobContainer" value="dist" />
<setting key="StreamCachedImage" value="false" />
It seems to work fine but i'm not sure about what is my optimal setting for the "StreamCachedImage" option.
I did some tests locally and with StreamCachedImage set to false it do a redirect to the CDN and i get a 302 and then a 200 from the CDN, and chrome says it cached so just a few bytes is transferred.
First:
Second:
When i switch to StreamCachedImage true i do not get a redirect and only get a 200 but it seems like it always returns the full image to the client.
I should also add that on top of this we also run Cloudflare against both example.com and d.example.com
But well, i basically would like to get some advice on how to set this up and to understand it fully.

Cannot use SQL server (LocalDB) after moving from IIS Express to Local IIS

When I run my website under local IIS instead of embedded IIS express I got the following error when accessing database (mdf file at app_data)
A network-related or instance-specific error occurred while
establishing a connection to SQL Server. The server was not found or
was not accessible. Verify that the instance name is correct and that
SQL Server is configured to allow remote connections. (provider: SQL
Network Interfaces, error: 26 - Error Locating Server/Instance
Specified)
Here the connection string:
Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Sources\Local\WebApplication1\WebApplication1\App_Data\aspnet-WebApplication1-20140226022052.mdf;Integrated Security=True
From Visual Studio and IIS Express I could connect to that database:
https://db.tt/rBXiwyA5
But the issue is that I need to have access to deployed application from another computer and IIS Express doesn't allow remote connections. That is why I was forced to use Local IIS.
Thank you for any advises!
you may need to double escape the \
"Data Source=(LocalDB)\v11.0;Integrated Security=true"
Unable to connect to localDB in VS2012 – "A network-related or instance-specific error occurred while establishing a connection to SQL Server..."
If you are using EntityFramework, try put it on App.config, worked for me.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
There are couple of things to try:
Provide the connection string in the format of, e.g.
Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=aspnet-WebApplication;Integrated Security=SSPI
On IIS, right click on the related App Pool then go to Advanced Settings, then set "Load User Profile" to true.
In my experience this did not change anything, so I had to do this manually in the applicationHost.config file found in C:\Windows\System32\inetsrv\config. Specifically, make sure "loadUserProfile" and "setProfileEnvironment" properties are set to true:
<applicationPools>
..
<add name="MyAppPool" autoStart="true" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated">
<processModel identityType="ApplicationPoolIdentity" loadUserProfile="true" setProfileEnvironment="true" />
</add>
..
<applicationPools>
Alternatively you could try changing Identity under App Pool
Advanced Settings from ApplicationPoolIdentity to
LocalSystem.
After doing one of these things you will hopefully stop getting this error, yet you may find that the application behaves as if there is no data in the database. This is because unlike SQLExpress or SQL Server, LocalDB runs as a user-specific process. Hence you might need to seed the database for the current database user (depending on the Application Pool/Identity being used) .
these links might provide an answer:
http://blogs.msdn.com/b/sqlexpress/archive/2011/12/09/using-localdb-with-full-iis-part-1-user-profile.aspx
http://blogs.msdn.com/b/sqlexpress/archive/2011/12/09/using-localdb-with-full-iis-part-2-instance-ownership.aspx

Azure mod-rewrite to SSL doesn't work

I have deployed an ASP.NET web application to Azure running in a web role. It is configured with a DNS name like 'myapp.cloudapp.net' and SSL (the certificate is self-signed, meaning we get a certificate warning but otherwise this is all set up and works fine)
I want to automagically route requests the come on http to https. So, I added an http endpoint and set up a rewrite rule as per the instructions here (second method):
http://blog.smarx.com/posts/redirecting-to-https-in-windows-azure-two-methods
It doesn't work properly.
Testing directly on the Azure machine (via remote desktop):
Access https://myapp.cloudapp.net - works
Access http://myapp.cloudapp.net - "Internet explorer cannot display the webpage"
So I go to IIS and 'browse' my site: this takes me there via the IP address:
Access https://[ipaddress] - works
Access http://[ipaddress] - works! Sends me to https://[ipaddress]
So what am I missing, that this works via IP address but not by host name?
I would like to hit http://myapp.cloudapp.net and be redirected to https://myapp.cloudapp.net.
For the record, here is the relevant parts of my configuration:
<Sites>
<Site name="Web">
<Bindings>
<Binding name="Endpoint1" endpointName="MyApp" />
<Binding name="Endpoint1" endpointName="MyAppHttp" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="MyApp" protocol="https" port="443" certificate="MYCERT" />
<InputEndpoint name="MyAppHttp" protocol="http" port="80" />
</Endpoints>
<Certificates>
<Certificate name="MYCERT" storeLocation="LocalMachine" storeName="My" />
</Certificates>
Can anyone help explain what I might be doing wrong?
Thanks in advance
Not a lot to go on, but one thing that jumps out at me is the 'name' of your bindings. Make them different.

Resources