Sending an emal from gmail in python 3 - email

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.

Related

SNMPTraps: pysnmp and "disableAuthorization"

I have written an SNMP trap receiver but currently I have to hardcode all the SNMPv2 community strings to be able to receive the traps.
How do I emulate the 'disableAuthorization' functionality from snmptrapd in pysnmp?
I have tried to not set the community string: config.addV1System(snmpEngine, 'my-area') but this errors about a missing param. I have also tried an empty string: config.addV1System(snmpEngine, 'my-area', '') but this stops all traps being processed.
What is the best way to allow receiving all traps through pysnmp regardless of the community string they were sent with? I haven't found anything in the pysnmp docs that could help me
I had made progress on setting up an observer for V1/2 (V3 to be added later) that picked up on notifications with an unknown community string and then called addV1System on the fly to dynamically add it in, like so:
When setting up the transportDispatcher:
snmpEngine.observer.registerObserver(_handle_unauthenticated_snmptrap,
"rfc2576.prepareDataElements:sm-failure", "rfc3412.prepareDataElements:sm-failure")
And then:
def _handle_unauthenticated_snmptrap(snmpEngine, execpoint, variables, cbCtx):
if variables["securityLevel"] in [ 1, 2 ] and variables["statusInformation"]["errorIndication"] == errind.unknownCommunityName:
new_comm_string = "%s" % variables["statusInformation"].get("communityName", "")
config.addV1System(my_snmpEngine, 'my-area', new_comm_string)
return
else:
msg = "%s" % variables["statusInformation"]
print(f"Trap: { msg }")
However, this will always throw away the first trap received while adding any new community string (and then there is the problem whereby when the daemon is restarted the updated list of community strings is lost).
In looking to improve this I then found hidden away in the docs this little gem:
https://pysnmp.readthedocs.io/en/latest/examples/v3arch/asyncore/manager/ntfrcv/advanced-topics.html#serve-snmp-community-names-defined-by-regexp
This example receives a notification and rewrites the community string into 'public' so all traps will be correctly received.
In essence, when setting up the transportDispatcher:
my_snmpEngine.observer.registerObserver(_trap_observer,
'rfc2576.processIncomingMsg:writable', cbCtx='public')
And then:
def _trap_observer(snmpEngine, execpoint, variables, community_string):
variables['communityName'] = variables['communityName'].clone(community_string)

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}}"

IDA "call offset"

I've dumped a dll from memory using LordPE, so far so good, but there are some functions IDA shows just like this:
call off_11CAE08
At memory address 11CAE08(.data section) we have 01058530(.text section) so I'd like IDA was able to show call sub_01058530, so, Is there any way or script that's able to change and fix all lines with this problem?
It's a relative call, you need to resolve that address. You can do this statically by looking at the library or you can do it dynamically by using a tool called Ablation, you can learn how to use it by listening to the authors talk at black hat. In order to do that you need to run the process/dll with ablation
Assuming you have 1-dref functions like this one, here is a script using sark:
from sark import *
from idc import *
from idaapi import *
from idautils import *
import struct
text_start =xxx
text_end= xxxx
data_start=xxx
data_end=xxx
for line in sark.lines(text_start, text_end):
for ref in line.xrefs_to:
if ref.type.is_call:
if data_start <= ref.to <= data_end:
addr = GetManyBytes(ref.to, 4)
addr, _ = struct.unpack("<I", addr)
MakeName(ref.to, "func_ptr_"+str(addr))
P.S. Im writing from my phone, so syntax may not be exact.

issue with rpyc marshalling of objects

I am using rpyc (v 3.3.0) to get the list of processes running on a remote server using psutil module. My code is as below.
server='hkl20056309'
rpcClient = rpyc.classic.connect(server)
rpsutil = rpcClient.modules.psutil
procs = rpsutil.get_process_list()
I am getting the list of procs correctly but some of the processes attributes are not set correctly. for example:
>>> procs[166]._name
'mingetty'
>>> procs[140]._name
>>> procs[141]._name
>>> procs[142]._name
>>> procs[142]
<psutil.Process(pid=1828, name='gatengine') at 17483536>
>>> procs[142]._name
'gatengine'
>>>
If you see procs[142]._name is not printed (value is None) until I access the object. If I print all the processes, I see the name as None for 143rd process object in the list. But after I access the object, suddenly I can see the correct value for the name.
Any suggestions on how I can resolve this issue?
Never seen such an issue with RPyC. It's probably something to do with that Process. If you call str(proc) and then proc._name, instead of printing, does it help? Also, it seems like you're trying to use a private member (_name)... Perhaps that's the issue? Isn't there some public property you can use?

After querying DB I can't print data as well as text anymore to browser

I'm in a web scripting class, and honestly and unfortunately, it has come second to my networking and design and analysis classes. Because of this I find I encounter problems that may be mundane but can't find the solution to it easily.
I am writing a CGI form that is supposed to work with a MySQL DB. I can insert and delete into the DB just fine. My problem comes when querying the DB.
My code compiles fine and I don't get errors when trying to "display" the info in the DB through the browser but the data and text doesn't in fact display. The code in question is here:
print br, 'test';
my $dbh = DBI->connect("DBI:mysql:austinc4", "*******", "*******", {RaiseError => 1} );
my $usersstatement = "select * from users";
my $projstatment = "select * from projects";
# Get the handle
my $userinfo = $dbh->query($usersstatement);
my $projinfo = $dbh->query($projstatement);
# Fetch rows
while (#userrow = $userinfo->fetchrow()) {
print $userrow[0], br;
}
print 'end';
This code is in an if statement that is surrounded by the print header, start_html, form, /form, end_html. I was just trying to debug and find out what was happening and printed the statements test and end. It prints out test but doesn't print out end. It also doesn't print out the data in my DB, which happens to come before I print out end.
What I believe I am doing is:
Connecting to my DB
Forming a string the contains the command/request to the DB
Getting a handle for my query I perform on the DB
Fetching a row from my handle
Printing the first field in the row I fetched from my table
But I don't see why my data wouldn't print out as well as the end text. I looked in DB and it does in fact contain data in the DB and the table that I am trying to get data from.
This one has got me stumped, so I appreciate any help. Thanks again. =)
Solution:
I was using a that wasn't supported by the modules I was including. This leads me to another question. How can I detect errors like this? My program does in fact compile correctly and the webpage doesn't "break". Aside from me double checking that all the methods I do use are valid, do I just see something like text not being displayed and assume that an error like this occurred?
Upon reading the comments, the reason your program is broken is because query() does not execute an SQL query. Therefore you are probably calling an undefined subroutine unless this is a wrapper you have defined elsewhere.
Here is my original posting of helpful hints, which still apply:
I hope you have use CGI, use DBI, etc... and use CGI::Carp and use strict;
Look in /var/log/apache2/access.log or error.log for the bugs
Realize that the first thing a CGI script prints MUST be a valid header or the web server and browser become unhappy and often nothing else displays.
Because of #3 print the header first BEFORE you do anything, especially before you connect to the database where the script may die or print something else because otherwise the errors or other messages will be emitted before the header.
If you still don't see an error go back to #2.
CGIs that use CGI.pm can be run from a command line in a terminal session without going through the webserver. This is also a good way to debug.