I have a Laravel app sending emails via MailGun. For Gmail addresses it works right of the bat, but for Outlook/Hotmail they are marked as spam and have broken formatting. I have identified some issues but not sure how to best fix them.
I am aware this post is broad but the common thing is how to please outlook/hotmail.
Multipart messages
According to MailGun help:
It is best to send multi-part emails using both text and HTML or text only. Sending HTML the only email is not well received by ESPs.
Given my Mailables' build function below, how can I achieve that?
public function build()
{
return $this->from('name#mysite.com')
->subject('Welcome to mysite!')
->view('emails.welcome_new_user', [
'updateLink' => env('APP_URL') . '/subscribers/' . $this->subscriber->id . "/edit/" . $this->subscriber->token,
'deleteLink' => env('APP_URL') . '/subscribers/' . $this->subscriber->id . "/delete/" . $this->subscriber->token
]);
}
Headers
According to MailGun help:
Make sure you are using unsubscribe links and headers in your emails. Many ESPs (particularly Hotmail) pay attention to this and if they are not there, you are likely to get filtered.
In the view I have two unsubscribe links, one as a button in the body and one in the footer as plain text link so that should be fine. But how do I supply Headers and which headers? I assume it is done similar to this section in Laravel docs:
$message->getHeaders()->addTextHeader('Custom-Header', 'HeaderValue');
Other tips on specific Outlook/Hotmail requirements
Also most appreciated
I send invitation by mail to users with a encrypted email to know which user respond to invitation. Something like:
Hello, click on this link to start learning: https://example.org/start-learning?e=fwTreaN0WybffXdDfZZUNYB3FTFfZObCb7QFF5C4AFJvTjXabIPtRfcoXLkFYMUvD4FIZsmrDdEFN2OPKcTrAOSQLZfuKdfwcic1WtBxWSXWR1GEJD6we213A3BEPBpca0BxaaQ4GGMPFeRyXp6fPrG9WnTgWogwXUcnVtdwSEEdNHGuZsClTxR2AtD2JZN8VAEsRQKpFFShEDR2SET4KxGhLGM3M0FdDelrJtO8KXS2YRaddH==
The encrypted email is the long string above. I encode mail like this in a Mailable class:
$url = 'https://example.org/start-learning?e=' . encrypt($this->to[0]['address']);
Then this $url is added in a mail template like this:
<a href="{{$url}}>click me<a>
Then, when user clicks the link, it routes to a controller and the controller decrypts the payload:
decrypt($request->input('e'));
Then, it works for about 99% of people clicking link. But for about one percent, it does not work, I have an error decrypting. And I don't know why. This is the same Laravel application which encrypts and decrypts. Is there an reason for such a weird behavior?
Side note: I know decrypt always work and has not a random behavior (BTW I tested it on 10000 entries, it's OK). There must be something else with the mail process I don't understand.
I think you should use urlencode() when creating link so instead of:
$url = 'https://example.org/start-learning?e=' . encrypt($this->to[0]['address']);
you should use:
$url = 'https://example.org/start-learning?e=' . urlencode(encrypt($this->to[0]['address']));
to make sure it will be valid.
I made a module named Gallery which works fine on my localhost with version 2.0.3, but when using version 2.1.0 on a remote site I can not submit a form and I get the error:
The action you have requested is not allowed.
Why is this?
I agree with #Jhourlad Estrella on fixing the problems instead of disabling a security feature, however I feel that the real problem is with the hidden input field that holds the token.
Instead of using plain HTML to create a form element use the the form_open() and form_close() helper functions. The reason why is because when you use the helper function it automatically inserts the csrf token as a hidden field in the form.
You could do this manually as well by adding the token as a hidden input field in the form
<input type="hidden" name="csrf_hash_name" value="your-hash-value-here">
Doing it this way will allow you to stay protected from CSRF attacks and fix the problem you are having.
Hope this helps someone else out there as this was driving me nuts the first time figuring this out.
It is a Codeigniter error related to the CSRF protection. You can cancel it in cms/config/config.php
On matters of programming, you don't go around problems, you fix it. What I mean to say is, this feature won't be here if it is unusable: 'coz it is and it works for me. You just have a problem on the implementation.
My answer: Remove all dashes, periods and any other non-alphanumeric characters from the values of following entries on application/config/config.php as seen below:
$config['sess_cookie_name'] = 'mycookiename'; //instead of "my_cookie_name"
$config['csrf_token_name'] = 'mycsrftoken'; //instead of "my.csrf.token"
$config['csrf_cookie_name'] = 'mycsrfcookie'; //instead of "my/csrf/cookie"
BTW, dashes sometimes work but I suggest using single words whenever possible when naming config values. Not unless you have the time and skills to study Codeigniter's core files related to what ever you are working on just to make sure it's safe to do so.
Anyways, I hope this help somebody out there even though my answer is more than a year late.
I have a form that was built outside of CI (in Joomla), but that I wanted to process with CI. My fix was to selectively disable csrf for specific referrers. I added this to config, directly after the default config options for csrf:
/* Set csrf off for specific referrers */
$csrf_off = array(
"http://yourdomain.com/your-form-url",
"http://yourdomain.com/some-other-url"
);
if (isset($_SERVER["HTTP_REFERER"])) {
if (in_array($_SERVER["HTTP_REFERER"],$csrf_off)) {
$config['csrf_protection'] = false;
}
}
This disables csrf protection for specific URLs in the $csrf_off array, but leaves it intact for all other requests.
I have found using the form helper functions
Example
<?php echo form_open('controller/function');?>
<?php echo form_input('username', 'Username');?>
<?php echo form_close();?>
Using the helper functions like above should stop the CSRF error message showing.
If I don't use echo form_input() if I place just normal input will trigger the CSRF error when reload.
<?php echo form_open('controller/function');?>
<input type="text" name="username" />
<?php echo form_close();?>
So I recommend using all form helper functions now.
It is an old question but this same problem did cost me so much time that I wanted to share what the problem was in my case. It may help someone.
I am using Codeigniter 3.0.6 and CommunityAuth 3 together with it and I was getting this error after a login.
It was confusing since the problem would sometimes happen and would not other times.
My 'base_url' in CI's config.php was set to something like 'www.mysite.com'
When you browse the site with 'mysite.com' (notice 'www' is not in the address) and you do a form submission that uses CI's 'base_url' setting, like CommunityAuth's login does, then CSRF check fails and you get 'The action you have requested is not allowed.' error.
This error is thrown by the function csrf_show_error() in system/core/Security.php when the CSRF token in $_COOKIE doesn't match your $_POST['csrf_token_name'].
Inside config.php, I had to ensure that $config['cookie_domain'] matched $config['base_url'], without the protocol (i.e. http(s)://).
Otherwise, the cookie wasn't being passed which meant the match couldn't be made.
Use the codeigniter form opener like this:
<php echo form_open(url,method,attributes);?>
see codeigniter form documentation for more.
This is probably a rare case, but I didn't see my issue since my server has many different domain names that are very similar. The problem was that I was landing on a domain that was completely wrong, but since "The action you have requested is not allowed." error takes precedence over " 404 Not Found Error" I couldn't see it. My problem was that I didn't change my base_url to the correct domain. So if none of the above solutions work for you, you might check your settings for $config['base_url'] in application/config.
For me the problem was that I was loading the view in the index, than I changed as follow and it worked:
public function index()
{
// Load Login Page
redirect('login/login_page','refresh');
}
public function login_page()
{
$data['title'] = 'Login Page';
$this->load->view('templates/header', $data);
$this->load->view('users/login_view', $data);
$this->load->view('templates/footer');
}
Im Using Codeigniter 3 same problem with
The action you have requested is not allowed.
Based on Isaac Pak's point, i changed my base_url to what i usally typed at the address bar. like this...
instead of putting
http://www.domain.org
i write it this way..
http://domain.org
since my base_url() is just..
$config['base_url'] = 'http://domain.org/';
the fix works for my site...
I need to find the user agent string, which it looks like UserAgentSTring.com does for me but I need to store that so I can pass it to the server side. I am not sure how to accomplish this?
The API docs say this:
You can send a ua string as post or get request (form field or in the query string).
Use 'uas' as parameter name:
?uas=Opera/9.70%20(Linux%20i686%20;%20U;%20en-us)%20Presto/2.2.0
this will automatically parse the string. To get some data you have to add one more parameter:
But if I put that line in my source code, in the header of my page how will the server side recognize it? Any assistance would be great.
If you are using PHP you can just use $_SERVER['HTTP_USER_AGENT'] but if that is not what you are looking for, look into HTML forms. Putting it in the header of your source code will do nothing for the server if it is not in PHP/ASP
Server-side approach with PHP:
<html>
<body>
Hi! You're using:
<?php
$jsonText = file_get_contents("http://useragentstring.com/?getJSON=all&uas=" + urlencode($_SERVER['HTTP_USER_AGENT']));
$obj = json_decode($jsonText, true);
echo $obj['agent_name'] . " " . $obj['agent_version'] . " on " . $obj['os_name'];
?>
Lol.
</body>
</html>
A client-side approach with Javascript is a bit more complex and you are better off not using useragentstring.com for this but using the browser's built-in mechanisms, like here.
I'm trying to read an email using ruby mail gem.
But mail.body.decoded returns me not just the body message. How can I clean up this body message and remove unwanted text like:
-20cf30433c9a437cc304939017ef\nContent-Type: text/plain; charset=ISO-8859-1\nContent-
message = $stdin.read
mail = Mail.read_from_string(message)
puts mail.body.decoded
--20cf30433c9a437cc304939017ef\nContent-Type: text/plain; charset=ISO-8859-1\nContent-Transfer-Encoding: quoted-printable\n\n REAL BODY TEXT \\n\n--20cf30433c9a437cc304939017ef\nContent-Type: text/html; charset=ISO-8859-1\nContent-Transfer-Encoding: quoted-printable\n\n<br clear=3D\"all\">--20cf30433c9a437cc304939017ef--
How can I clean up this email body mail message extracting only the REAL BODY TEXT , without ANY header ?
I'm creating a simple Ticket System based in Ruby on Rails, and a ticket is created when an email is received by ticket#mydomain.com. But when the message is in HTML format the BODY TEXT is surrounded by HEADERs text.
If you have a properly formatted email, you can use Mail helper methods:
mail = Mail.new(email_string)
mail.text_part # finds the first text/plain part
mail.html_part # finds the first text/html part
This doesn't always work if you have e.g. single part messages (text only) or receive email from the internet at large since you can't rely on formatting from every client out there. Believe me, I've learned the hard way.
looks like you've got a multipart email, so you can use
mail.parts[0].body.decoded
These will probably come in handy too:
mail.multipart?
mail.parts.length
The gem documentation at github is pretty decent
With the mail gem, you can do:
text = mail.multipart? ? mail.text_part.decoded : mail.body.decoded`
Add the mail gem and just use email body format with mail.parts[1].body.decoded.