When I try to connect to the Gmail server, python throws an error:
>>> from smtplib import SMTP
>>> m = SMTP('smtp.gmail.com', 587)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\smtplib.py", line 249, in __init__
(code, msg) = self.connect(host, port)
File "C:\Python27\lib\smtplib.py", line 309, in connect
self.sock = self._get_socket(host, port, self.timeout)
File "C:\Python27\lib\smtplib.py", line 284, in _get_socket
return socket.create_connection((port, host), timeout)
File "C:\Python27\lib\socket.py", line 571, in create_connection
raise err
socket.error: [Errno 10060]
The rest of the output is in a diferent language but it basically says that the host (gmail) didn't respond.
I can see my email on a browser here at my work, probably there's a network configuration that doesn't allow me to automate the email delivering.
Is there a work around to let python act as a regular browser?
First, you can only access gmail's SMTP servers as a client with some form of authentication; the recommended way is with oauth. See this page and this one for details. So, your code won't work, even when you get past this problem.
However, that doesn't explain why it's rejecting your connection before you even get a chance to log in.
The most likely possibility is that gmail's routers are maintaining a dynamic whitelist of IPs. When you use a properly-logged-in connection of some other kind, you get added to the whitelist for N seconds, meaning you're allowed to connect to port 587; otherwise, you're rejected. This would be similar to the traditional SMTP-after-IMAP auth scheme, but not restricted to IMAP, and handled at the router instead of the SMTP service (presumably to lower the cost or make DoS attacks more difficult).
There's a good way to test this: Configure Outlook, Mail.app, or some other mail client that knows how to connect to gmail, and uses SMTP to send mail via gmail. Run your script a few seconds after fetching mail in the mail client. If it works, that's the problem. And in that case, the fix is to do the same kind of connection and login (IMAP? web service?) that the mail client does.
Or, of course, you can use the sample code Google provides at the above links instead of working it out from first principles.
(Of course gmail also has to accept server-to-server SMTP connections, but they could easily have a different auth scheme for that. I'm assuming you're trying to do a client-to-server connection, rather than server-to-server.)
The other possibility is that you're on some kind of blacklist—e.g., gmail thinks your IP belongs to a spammer. This could also be dynamic—maybe anyone who makes a connection to port 587 but doesn't oauth properly gets blocked for the next N seconds. At any rate, this is also easy to test: Configure Outlook, Mail.app, etc. If this is the problem, they won't be able to send mail either.
There's a third possibility, that no one is allowed to connect to port 587, and Google wants you to use port 565 or 25 instead.
For easier debugging, you might want to consider writing an even simpler script that just creates a socket and connects, instead of using smtplib:
import socket
s = socket.socket()
s.connect(('smtp.gmail.com', 587))
Or, even more simply, just netcat from the command line:
nc smtp.gmail.com 587
To answer your side question:
Is there a work around to let python act as a regular browser?
That's not the issue. A regular browser doesn't make SMTP connections; it makes web service connections using Javascript code downloaded from gmail.com.
Of course Python can also make web services connections.
And it can act as much or as little like a "regular browser" (e.g., User-Agent, Referer, etc. headers) as you desire, but that probably isn't relevant—either the gmail web service API is public and has clear, published rules for how to authenticate yourself (in which case you just do what the rules say), or it's private and you shouldn't be trying to fool whatever protection they're using unless you want to get into an arms race.
At any rate, in this case, we know it's public, so we don't have to guess.
Related
A program I wanted to create requires to login to a mail server.
I was able to login using smtplib on Gmail, but it didn't work on Yahoo mail.
SMTP Port 465
Server mail: smtp.mail.yahoo.co.jp
python code on IDLE
import smtplib
smtp_obg = smtplib.SMTP("smtp.mail.yahoo.co.jp", 465)
Error message
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
smtp_obg = smtplib.SMTP("smtp.mail.yahoo.co.jp", 465)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/smtplib.py", line 253, in __init__
(code, msg) = self.connect(host, port)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/smtplib.py", line 341, in connect
(code, msg) = self.getreply()
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/smtplib.py", line 398, in getreply
raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed
I would appreciate if someone could help. Thank you in advance.
You must run login after creating smtp_obj (smtp_obg.login('username', 'password')). If you trying to login, please mention it.
You must activate SMTP feature at Yahoo's web page (Same as Gmail). Sorry for Japanese, but not sure if yahoo.co.jp is using somewhere outside Japan. :)
In English, this parameter should be called like: IMAP/POP/SMTP access and mail transfer
I checked my account. STMP access is disabled by default.
When you create a connection to your smtp server you need to know more about the server about what way you want to connect to it.
There are normal with and without SSL connection based on port number to your SMTP server.
I use this site https://settings.email/yahoo-co-jp-email-settings/ to get more info about your SMTP server you want to use from yahoo and it says the port 465 is an SSL connection so you need to connect with SSL connection else you can't sending out this way.
in smtplib in python you have smtplib.SMTP and smtplib.SMTP_SSL functions to work with, the first it's used when it's not SSL requirement, and the second its used when you need SSL like yahoo smtp.
Can you try out to use smtplib.SMTP_SSL function and see about its working for you?
import smtplib
smtp_obg = smtplib.SMTP_SSL("smtp.mail.yahoo.co.jp", 465)
Mabey its required a username and password to sending out, I did not have so much info about yahoo SMTP to can explain that part for you.
Im having some problem when joining Electron and Python using web sockets (mostly as a learning experience):
Build a desktop app using Electron Ok
Build a Python program that monitors some things Ok
Connect Python with Electron using socket.io Not working
First I tested socket.io in python with the 'latency' example in https://github.com/miguelgrinberg/python-socketio/tree/master/examples/server/aiohttp. It worked great when I took a look at http://localhost:8080/ in Chrome.
The next step was to ask Electron to load the same url in the desktop app with mainWindow.loadURL('http://localhost:8080') (I used the template from the official electron-quick-start example). I just had to add two lines into the html as shown in here: Electron: jQuery is not defined for jquery to load correctly in Electron, but it again worked nicely.
Now I tried to create an index.html with the same content as latency.html and load it with mainWindow.loadFile('gui/index.html'). I changed the line var socket = io.connect(); for var socket = io.connect('ws://localhost:8080'); (I did also tried ws://127.0.0.1:8080 and ws://192.168.<x>.<x>:8080). The html file loads correctly but the socket begins to connect and disconnect repeatedly with a Bad Request error (I added two console.log lines):
(console.log) connected
(error) POST http://localhost:8080/socket.io/?EIO=3&transport=polling&t=MosNuF3&sid=c62ce5a6090c4b72bf3f7c6916da6ce7 400 (Bad Request) **polling-xhr.js:264**
(console.log) disconnected
(warning) websocket.js:235 WebSocket connection to 'ws://localhost:8080/socket.io/?EIO=3&transport=websocket&sid=c62ce5a6090c4b72bf3f7c6916da6ce7' failed: WebSocket is closed before the connection is established.
(error) POST http://localhost:8080/socket.io/?EIO=3&transport=polling&t=MosNuFS&sid=c62ce5a6090c4b72bf3f7c6916da6ce7 400 (Bad Request) **polling-xhr.js:264**
(console.log) connected
etc...
(console.log) disconnected
etc...
On the server side there is also an error when I stop the Electron app:
Unhandled exception
Traceback (most recent call last):
File "D:\Programming\Tools\Anaconda3\lib\site-packages\aiohttp\web_protocol.py", line 447, in start
await resp.prepare(request)
File "D:\Programming\Tools\Anaconda3\lib\site-packages\aiohttp\web_response.py", line 353, in prepare
return await self._start(request)
File "D:\Programming\Tools\Anaconda3\lib\site-packages\aiohttp\web_response.py", line 667, in _start
return await super()._start(request)
File "D:\Programming\Tools\Anaconda3\lib\site-packages\aiohttp\web_response.py", line 410, in _start
await writer.write_headers(status_line, headers)
File "D:\Programming\Tools\Anaconda3\lib\site-packages\aiohttp\http_writer.py", line 112, in write_headers
self._write(buf)
File "D:\Programming\Tools\Anaconda3\lib\site-packages\aiohttp\http_writer.py", line 67, in _write
raise ConnectionResetError('Cannot write to closing transport')
ConnectionResetError: Cannot write to closing transport
What does this Bad Request error mean in this context ? How would the connection work correctly ?
Thanks.
In case someone hits the same problem. The answer is pretty simple, from the documentation for socket.io here:
For security reasons, this server enforces a same-origin policy by
default. In practical terms, this means the following:
If an incoming HTTP or WebSocket request includes the Origin header, this header must match the scheme and host of the connection
URL. In case of a mismatch, a 400 status code response is returned and
the connection is rejected.
No restrictions are imposed on incoming requests that do not include the Origin header.
If necessary, the cors_allowed_origins option can be used to allow
other origins. This argument can be set to a string to set a single
allowed origin, or to a list to allow multiple origins. A special
value of '*' can be used to instruct the server to allow all origins,
but this should be done with care, as this could make the server
vulnerable to Cross-Site Request Forgery (CSRF) attacks.
When using electron to load the gui, the server is not the same as the python server that's doing the monitoring, thus the Bad Request (not same origin). The solution is to just modify as follows the server properties adding cors_allowed_origins='*':
socketio.AsyncServer(async_mode='aiohttp', cors_allowed_origins='*')
I'm trying to connect to control port (9051) of tor from a remote machine using stem python library.
dum.py
from stem import Signal
from stem.control import Controller
def set_new_ip():
"""Change IP using TOR"""
with Controller.from_port(address = '10.130.8.169', port=9051) as controller:
controller.authenticate(password='password')
controller.signal(Signal.NEWNYM)
set_new_ip()
I'm getting the following error
Traceback (most recent call last):
File "/home/jkl/anaconda3/lib/python3.5/site-packages/stem/socket.py", line 398, in _make_socket
control_socket.connect((self._control_addr, self._control_port))
ConnectionRefusedError: [Errno 111] Connection refused
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "dum.py", line 28, in <module>
set_new_ip();
File "dum.py", line 7, in set_new_ip
with Controller.from_port(address = '10.130.4.162', port=9051) as controller:
File "/home/jkl/anaconda3/lib/python3.5/site-packages/stem/control.py", line 998, in from_port
control_port = stem.socket.ControlPort(address, port)
File "/home/jkl/anaconda3/lib/python3.5/site-packages/stem/socket.py", line 372, in __init__
self.connect()
File "/home/jkl/anaconda3/lib/python3.5/site-packages/stem/socket.py", line 243, in connect
self._socket = self._make_socket()
File "/home/jkl/anaconda3/lib/python3.5/site-packages/stem/socket.py", line 401, in _make_socket
raise stem.SocketError(exc)
stem.SocketError: [Errno 111] Connection refused
Then I went through /etc/tor/torrc config file.
It says
The port on which Tor will listen for local connections from Tor
controller applications, as documented in control-spec.txt.
ControlPort 9051
## If you enable the controlport, be sure to enable one of these
## authentication methods, to prevent attackers from accessing it.
HashedControlPassword 16:E5364A963AF943CB607CFDAE3A49767F2F8031328D220CDDD1AE30A471
SocksListenAddress 0.0.0.0:9050
CookieAuthentication 1
My question is ,
How do I connect to control port of Tor from a remote host?
Is there is any work around or config parameter that I need to set?
a possible duplicate of Stem is giving the "Unable to connect to port 9051" error which has no answers
Tested with Tor 0.3.3.7.
ControlListenAddress config is OBSOLETE and Tor will ignore it and log the following message
[warn] Skipping obsolete configuration option 'ControlListenAddress'
You can still set ControlPort to 0.0.0.0:9051 in your torrc file. Though, Tor is not very happy about it (and rightly so) and will warn you
You have a ControlPort set to accept connections from a non-local
address. This means that programs not running on your computer can
reconfigure your Tor. That's pretty bad, since the controller protocol
isn't encrypted! Maybe you should just listen on 127.0.0.1 and use a
tool like stunnel or ssh to encrypt remote connections to your control
port.
Also, you have to set either CookieAuthentication or HashedControlPassword otherwise ControlPort will be closed
You have a ControlPort set to accept unauthenticated connections from
a non-local address. This means that programs not running on your
computer can reconfigure your Tor, without even having to guess a
password. That's so bad that I'm closing your ControlPort for you. If
you need to control your Tor remotely, try enabling authentication and
using a tool like stunnel or ssh to encrypt remote access.
All the risks mentioned in #drew010's answer still stand.
You'd need to set ControlListenAddress in addition to the ControlPort. You could set that to to 0.0.0.0 (binds to all addresses) or a specific IP your server listens on.
If you choose to do this it would be extremely advisable to configure your firewall to only allow control connections from specific IP's and block them from all others.
Also note, the control port traffic will not be encrypted, so it'd also be advisable to use cookie authentication so your password isn't sent over the net.
You could also run a hidden service to expose the control port over Tor and then connect to the hidden service using Stem and Tor.
But the general answer is ControlListenAddress needs to be set to bind to an IP other than 127.0.0.1 (localhost).
Im writing HTTP Proxy Server that will open socket with the browser and the request from the browser will go to my HTTP Proxy Server and my server will open socket with the server that the browser ask for and send him the request.
It will go like this:
Browser --request--> HTTP Proxy Server --request--> Web Server
Browser <--response-- HTTP Proxy Server <--response-- Web Server
Now I need those sockets will be clearly that I can use scapy to see the layers of each packet and manipulate it like I want to. (for security reasons e.g Block Phishing or something like that)
In this code I write simple socket with the browser just for testing and learning about browser behavior with HTTP Requests.
from scapy.all import *
import socket
socket_with_browser = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print "Start"
socket_with_browser.bind(('127.0.0.1',8080))
socket_with_browser.listen(1)
conn , addr = socket_with_browser.accept()
stream_sock_browser = StreamSocket(conn)
r = stream_sock_browser.recv(4096)
r[TCP].show()
socket_with_browser.close()
I get the following Error:
Traceback (most recent call last):
File "<string>", line 254, in run_nodebug
File "C:\Python26\ProxyServer\module1.py", line 22, in <module>
r[TCP].show()
File "C:\Python26\Lib\site-packages\scapy\packet.py", line 817, in __getitem__
raise IndexError("Layer [%s] not found" % lname)
IndexError: Layer [TCP] not found
There is a way that I can get packet from socket and use it (get packet layers or something) with scapy? Maybe I declare the socket badly? By the way Im using Windows 7 and python 2.6
Six years late but your question might appear to others with similar issues.
The problem with your approach is that not every packet received has a TCP layer, so you should use the haslayer() method.
if r.haslayer(TCP): # yes, without quotation marks
r.show()
I've tried playing around in python to learn more about the smtp protocol. More precisely I'm been trying to send a mail straight to a host's smtp server, but with little success.
For example, say I want to send a mail to a gmail.com address, I lookup the mx record for gmail.com:
>> nslookup -type=MX gmail.com
gmail.com MX preference = 40, mail exchanger = alt4.gmail-smtp-in.l.google.com
gmail.com MX preference = 5, mail exchanger = gmail-smtp-in.l.google.com
gmail.com MX preference = 10, mail exchanger = alt1.gmail-smtp-in.l.google.com
Then I do the following in python:
import smtplib
# Tried both port 465 and 587 (can't test port 25 since it's blocked by my ISP)
s = smtplib.SMTP("alt1.gmail-smtp-in.l.google.com", 587)
I tried several, and for everyone but one I always got a:
"[Errno 10051] A socket operation was attempted to an unreachable network" or
"[Errno 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because conneted host has failed to respond" exception.
I read somewhere that some mail servers do a reverse lookup on your IP, and rejecting the connection if it hasn't got a domain. How do they do that?
I also read somewhere that many mail servers reject incoming mails from dynamic IP addresses (which I obviously have as a private customer to my ISP). How can they check if an IP address is dynamic or static?
Are these the reasons most servers seem to reject my connection? Or is there something more to it?
Um, your problem is exactly this:
# Tried both port 465 and 587 (can't test port 25 since it's blocked by my ISP)
Google's MX server is listening on port 25. If your ISP does not allow outgoing connections on this port, then you will not be able to send SMTP messages the way you are trying to do. You should get this sorted out with your ISP.
Regarding the rejection of messages, sending e-mail directly like this does increase the likelihood that it will be rejected or flagged as spam. Particularly if you set the "from" address to something that does not match the domain associated with your IP address, or if your SMTP client sends a mismatched domain in its EHLO message, or if the content of your message looks "spammy". The actual behavior will vary according to how each individual MX server has been configured.
Direct to MX email like you describe above will be blocked by Gmail's SMTP servers, with an error message "421-4.7.0", however many other SMTP severs, like MailEnable will allow Direct To MX.
The following website has source code for .NET and PHP for Direct to MX code, http://www.directtomx.com - you may be able to consume the webservice in python using SUDS.