Postfix+Dovecot - How to receive mail for anyuser#anydomain - email

So the main idea is that I want to do something like this:
1) I send email to anyrandomuser#anyofmydomain.com
2) I receive it with Dovecot, or at least store it in maildir like:
/vmail/%anydomain/%anyuser
I tried something like this:
cat /etc/postfix/main.cf
inet_interfaces = all
inet_protocols = ipv4
relay_domains = *
virtual_mailbox_domains=hash:/etc/postfix/vmail_domains
virtual_mailbox_maps=hash:/etc/postfix/vmail_mailbox
virtual_mailbox_base = /var/vmail
virtual_minimum_uid = 2222
virtual_transport = virtual
virtual_uid_maps = static:2222
virtual_gid_maps = static:2222
cat /etc/postfix/vmail_mailbox
#d1.com d1.com/catchall/
#d2.com d2.com/catchall/
#d3.com d3.com/catchall/
So that is working pretty well. But its limited to domain-list in /etc/postfix/vmail_mailbox and all mails endup in the same directory. I tried to do some sorting with pcre-map like this:
cat /etc/postfix/vmail_mailbox_pcre
/([^\#]+)#([^\s]+)/ ${2}/${1}/
But it doesnt work. That's what i get in log:
Jan 26 09:41:04 localhost postfix/virtual[5579]: warning: pcre map /etc/postfix/vmail_mailbox_pcre, line 1: regular expression substitution is not allowed: skipping this rule
Has anyone done something like that? I'm open to any help. Thanks.

Receiving the mail seems to be working for you, the problem appears to be with sorting the mails depending on the recipient domain. The dovecot sieve extension might be what you want to use the sorting.
The problem with your /etc/postfix/vmail_mailbox_pcre is that the regexp separator (the /) is used more than twice, so the regexp engine gets confused. Try to use some other non-alphanumeric character instead:
#([^\#]+)#([^\s]+)# ${2}/${1}/

Related

Exim getting random credential in exim.conf

I have been trying to get perl subroutine value and substitution to get the required part of string from randomips subroutine in exim.conf. However when i use string substitution i get error as follow:
Here is what I am trying to achieve
I am trying to split string by colon and get first occurrence as "interface". I'll be using second occurrence as the "helo_data.
exim.pl
sub randomhosts {
#inet = ("x.x.x.1:hostname1.domain.com","x.x.x.2:hostname2.domain.com","x.x.x.3:hostname3.domain.com"
);
return $inet[int rand($#inet+1)];
}
exim.conf
dkim_remote_smtp:
driver = smtp
interface = "${perl{randomhosts}%:*}"
helo_data = "${sender_address_domain}"
Error I get is as follow:
"failed to expand "interface" option for dkim_remote_smtp transport: missing '}' after 'perl'".
Probably the syntax.
Any help?
The code that you are trying to copy was written by someone who doesn't know much about Perl. It includes this line:
return $inet[int rand($#inet+1)];
A Perl programmer would write this as
return $inet[rand #inet];
I think there are a couple of issues here - one with your Exim syntax and one with your Perl syntax.
Exim is giving you this error:
failed to expand "interface" option for dkim_remote_smtp transport: missing '}' after 'perl'
I don't know anything about calling Perl from Exim, but this page mentions a syntax like ${perl{foo}} (which is similar to the one used in the page you are copying from) and one like ${perl{foo}{argument}} for calling a subroutine and passing it an argument. Nowhere does it mention syntax like yours:
${perl{randomhosts}%:*}
I'm not sure where you have got that syntax from, but it seems likely that this is what is causing your first error.
In a comment, you say
I am stying to get first part of string before colon for each random array value for "interface" and part after colon for "helo_data"
It seems to me that Exim doesn't support this requirement. You would need to call the function twice to get the two pieces of information that you require. You might be able to do this in the Perl using something like state variables - but it would be far more complex than the code you currently have there.
Secondly, your Perl code has a syntax error, so even if Exim was able to call your code, it wouldn't work.
The code you're copying sets up #inet like this:
#inet = ("x.x.x.1", "x.x.x.2", "x.x.x.3", "x.x.x.4");
Your equivalent code is this:
#inet = (
"x.x.x.1:hostname1.domain.com",
"x.x.x.2:hostname2.domain.com,
x.x.x.3:hostname3.domain.com
);
I've reformatted it, to make the problems more obvious. You are missing a number of quote marks around the elements of the array. (Note: I see that while I have been writing this answer, you have fixed that.)
Update: Ok, here is some code to put into exim.pl that does what you want.
use feature qw[state];
sub randomhosts {
state $current;
my #inet = (
"x.x.x.1:hostname1.domain.com",
"x.x.x.2:hostname2.domain.com",
"x.x.x.3:hostname3.domain.com"
);
if ($_[0] eq 'generate') {
shift;
#{$current}{qw[ip host]} = split /:/, $inet[rand #inet];
}
return $current->{$_[0]};
}
It generates a new ip/host pair if its first argument is 'generate'. It will then return either the hostname or the ip address from the generated pair. I think you can probably call it from your Exim config file like this:
dkim_remote_smtp:
driver = smtp
interface = "${perl{randomhosts}{generate}{ip}}"
helo_data = "${perl{randomhosts}{host}}"
But I'm no expert in Exim, so that syntax might need tweaking.
First I would like to note I have not worked with exim so I cannot say what exactly you are trying to do and why you have done things exactly so.
In the link you posted, a method called 'randinet' is added to exim.pl and the interface line in exim.conf is replaced by
interface = "${perl{randinet}}"
You have implemented a 'randomhosts' method and replaced the interface line with
interface = "${perl{randomhosts}%:*}"
Now the parser complains about not finding the closing bracket. That is likely due to the symbols you felt free to add but the parser does not have the freedom to ignore.
I suggest you try
interface = "${perl{randomhosts}}"

Sending an emal from gmail in python 3

I'm doing my first project and was reading in my textbook and wrote this program,
import smtplib
password=input(str("Enter your password for example#gmail.com")
smtp0bj.ehlo()
smtp0bj.starttls()
smtp0bj.login('example#gmail.com',password)
smtp0bj.sendmail('example#gmail.com','example2#gmail.com','example3#hotmail.com','subject:Testmail\nTesting,testing,1,2,3,testing'
{}
smtp0bj.quit()
According to my textbook, Automate the Boring Stuff with Python by Al Sweigart, I'm right, but I keep getting an error message. Is there anything I'm doing wrong? Or have I missed a vital step?
One of your problems seems to be a syntax error at the start of the program: when you ask for the password input, you open two sets of brackets input(str(, then only close one set, so adding an extra close-brackets to the end should fix that problem.
You could however, replace the input(str("text")) with just input("text") as what you are trying to do there is convert a string into a string, which is just a waste of time, what you may be trying to do, however is get the input as a string (str(input("text"))), which is needless in this case, as inputs are automatically read as strings in python.
It also seems that you are not defining smtp0bj, I'm not sure where you got the name from, so perhaps another read of the textbook (I'm assuming the name came from the textbook) would reveal a missing line or two.
In case your code doesn't work out, here is a copy of a program that I use to send emails in Gmail through python:
from smtplib import SMTP_SSL as SMTP
import logging, logging.handlers, sys
from email.mime.text import MIMEText
try:
logger = logging.getLogger("__main__")
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
to="" #Recipient's email address
frm="" #Sender's email address
pswd="" #Sender's password
sub="" #Subject of email
text="" #Message to send
msg = MIMEText(text, 'plain')
msg['Subject'] = sub
msg['To'] = to
except Exception as err:
pass
try:
conn = SMTP("smtp.gmail.com")
conn.set_debuglevel(True)
conn.login(frm, pswd)
try: conn.sendmail(frm, to, msg.as_string())
finally: conn.close()
except Exception as exc:
print(exc)
logger.error("ERROR!!!")
logger.critical(exc)
sys.exit("Mail failed: {}".format(exc))
Hope this helps.
EDIT:
I found your book online (https://automatetheboringstuff.com/chapter16/) and found that you have missed a step, defining the smtp server. Adding in the line smtpObj = smtplib.SMTP('smtp.gmail.com', 587) will allow you to send emails from Gmail.
import smtplib
smtpObj = smtplib.SMTP('smtp.gmail.com', 587)
smtpObj.ehlo()
smtpObj.starttls()
smtpObj.login('MyEmailAddress#gmail.com', 'MyEmailPassword')
smtpObj.sendmail('MyEmailAddress#gmail.com', 'RecipientEmailAddress#example.com', 'Subject: SubjectText.\nMessage Text')
smtpObj.quit()
Also: Make sure that your program is not called email.py as tht is the name of one of the modules used in stmplib, so it will raise an AtributeError.

VB Script to change the from field of emails in Outbox

I have emails in my Outbox in Outlook and I'd like to run a vb script to change the from field of these emails to some other email
I managed to do the following but it doesn't work as I'd like to and therefore I am missing the main piece. I'd appreciate if someone could help.
intFolderOutbox = 4
msoFileDialogOpen = 1
' Load requied objects
Set WshShell = WScript.CreateObject("WScript.Shell") ' Windows Shell
Set ObjOlApp = CreateObject("Outlook.Application") ' Outlook
Set ns = ObjOlApp.GetNamespace("MAPI") ' Outlook
Set box = ns.GetDefaultFolder(intFolderOutbox) ' Outlook
For Each Item In box.Items
*** HERE IS WHAT I NEED TO REPLACE THE FROM FIELD ****
Item.sender = "email2#gmail.com"
Item.Update
Item.Save
Next
Something like the following works adding a recipient but I couldn't find the equivalent to the from field.
Item.Recipients.Add "email2#gmail.com"
Here is something that could help but it doesn't work in my case
Set oAddrEntry = CreateObject("MAPI.AddressEntry")
oAddrEntry.Name = SYSTEM_ADDRESS
oAddrEntry.resolve
Set oNewMsg.sender = oAddrEntry
oNewMsg.Update
oNewMsg.Send
Thanks
Firstly, once a message is submitted (and moved to Outbox) it cannot be touched - it belongs to the spooler.
Secondly, you cannot send on behalf of an arbitrary user. In case of Exchange, set the MailItem.SentOnBehalfOfName property to the name of the Exchange mailbox on whose behalf the current user can send. In case of POP3/SMTP accounts, set the MailItem.SendUsingAccount property to one of the accounts from the Namespace.Accounts collection.

Get IPv6 prefix using perl

I am trying to get the IPv6 Prefix from a given IPv6 Address given the prefix length.
I have already tried several modules (like Net::IP, Net::IPv6Addr, and Net::IPv6Address) but none seems to do exactly that.
Actually only Net::IPv6Address gives such a method but the result is not in IPv6 format.
For example:
The IPv6: FE80:0202:B3FF:FE1E::/56 should give a prefix of FE80:0202:B3FF:FE00:: but when I run this code:
use Net::IPv6Address;
my $IPv6Address = new Net::IPv6Address("FE80:0202:B3FF:FE1E::", 56);
my $prefix = $IPv6Address->prefix();
print $prefix;
I get 'fe800202b3fffe' (Not the proper IPv6 format)...
I did the same in Java using the com.googlecode.ipv6.IPv6Address and com.googlecode.ipv6.IPv6NetworkMask libraries and it worked perfectly.
Any ideas on how to do this?
Thanks to everyone in advance!
There are many modules that can do this. I would suggest Net::Works or NetAddr::IP. With Net::Works:
use v5.16;
use Net::Works::Network;
my $network = Net::Works::Network->new_from_string(
string => 'FE80:0202:B3FF:FE1E::/56' );
say $network->first;
This will output fe80:202:b3ff:fe00::.

How do I reset my LDAP password from Perl?

My company, like everyone else's, requires password resets from time to time. This is all good and well for security's sake, but I'd like to explore the challenge of resetting it through a script (notably because we can't use our previous 25 passwords; Perl is much quicker about cycling through a list two-dozen deep than my fingers are).
I'm trying to use Perl and Win32::OLE's LDAP connectors to reset my password. I've followed a couple of examples online, and have, briefly:
use strict;
use Win32::OLE;
my $dn = 'cn=name,dc=corp,dc=com';
my $ldap = Win32::OLE->GetObject('LDAP:');
my $ldap_user = $ldap->OpenDSObject('LDAP://' . $dn,'username','password',1);
$ldap_user->SetPassword('mySw337NewPassword');
And all I get for my troubles is:
Win32::OLE(0.1707) error 0x80070005: "Access is denied"
in METHOD/PROPERTYGET "SetPassword" at pw.change.pl line 8
Is this something that can be worked around? I've located the Net::LDAP::Extension::SetPassword module, but no dice there.
Thanks!
Update for Leon (Max, you're next):
You're correct, I should have specified better. I tried Win32::OLE, failed, then separately tried Net::LDAP::Extension::SetPassword and failed even harder.
As for my server: I'm not certain, I'm not the LDAP guy :) By running ->root_dse->get_value('supportedExtension') I can see that the setPassword OID is not set, so maybe it's just not meant to be.
Final props to barneyton!
Final solution:
use strict;
use Win32::OLE;
my $orig_password = 'password123Test';
my $target_password = 'password321Test';
my $dn = 'cn=myname,dc=corp,dc=com';
my $ldap = Win32::OLE->GetObject('LDAP:');
my $ldap_user = $ldap->OpenDSObject('LDAP://'.$dn,'myname',$orig_password,1);
my $tmp_password = '';
for ( my $i = 0; $i < 30; ++$i )
{
$tmp_password = 'password' . $i . 'ABC';
print 'Changing to ' . $tmp_password . "\n";
$ldap_user->ChangePassword($orig_password,$tmp_password);
$orig_password = $tmp_password;
sleep 1;
}
$ldap_user->ChangePassword($tmp_password,$target_password);
When you said you were trying to "reset" your password, I think you really meant change password rather than set password. There is a difference between the two. "SetPassword" requires god/admin privilege since you are setting a user's password to a new value regardless of whether the old password is known, while "ChangePassword" requires the user to actually know the old password. I'm assuming your account does not have admin privilege, else you would not have gotten 0x80070005: "Access is denied"
So instead of:
$ldap_user->SetPassword('mySw337NewPassword');
try this:
$ldap_user->ChangePassword('password', 'mySw337NewPassword');
By the way, I've never done this stuff in perl, so I'm just guessing. Hope this helps you out.
Net::LDAP::Extension::SetPassword doesn't have anything to do with any OLE LDAP object. Either you use Net::LDAP, or you use Win32::OLE->GetObject('LDAP:').
You didn't mention what server you're using. Setting passwords requires an extension to LDAP, so that is relevant.
Another thing to keep in mind is Active Directory does not let you set passwords unless you bind to port 636 using LDAPS.
You could try to write the value to userPassword which would be a password reset, and you might not have rights to do that.
Otherwise you could try in one operation (LDIF would show it as separated by a single dash on a line) remove the value of the old password and then add the value of the new password. That would be a password change event.