Writing simple SMTP server in python - python

I'm trying to write a simple smtp server program. I've written a simple smtp client (in C#) which sends an email. I've tested the program with smtp4dev. So far it all works fine.
I'd also like to write my own simple program which receives the email (instead of smtp4dev). I've tried a number of different code snippets (eg: Here) that I've found around the web but I can't seem to get them working.
I've also tried using twisted.
To start with I can see using TCPView that the port numbers in the code are not the ones being used.
I get the feeling that I'm missing something conceptual though and heading in the wrong direction.
EDIT
Here's the C# code in case you are interested
MailMessage mail = new MailMessage();
mail.Subject = "Your Subject";
mail.From = new MailAddress("test#test.com.au");
mail.To.Add("soslab#soslab.lab");
mail.Body = "Hello! your mail content goes here...";
mail.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient("LOCALHOST", 26);
smtp.EnableSsl = false;
try
{
smtp.Send(mail);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
here's the python code
import smtpd
import asyncore
class EmailServer(smtpd.SMTPServer):
def process_message(self, peer, mailfrom, rcpttos, data):
print 'a'
def run():
foo = EmailServer(('localhost', 26), None)
try:
asyncore.loop()
except KeyboardInterrupt:
pass
if __name__ == '__main__':
run()

For some reason this program runs fine when I run it from the command line
import smtpd
import asyncore
import winsound
class PYEmailServer(smtpd.SMTPServer):
def __init__(*args, **kwargs):
smtpd.SMTPServer.__init__(*args, **kwargs)
def process_message(self, peer, mailfrom, rcpttos, data):
winsound.Beep(2500, 1000)
def run():
foo = PYEmailServer(('localhost', 26), None)
try:
asyncore.loop()
except KeyboardInterrupt:
foo.close()
if __name__ == '__main__':
run()
It does not work when I run it from IDLE. (C# program just throws an exception like the service isnt there). I dont know why this would be, but I have my original problem working.

To test your smtp server you need to set the smtpclient object on another terminal
import smtplib
smtpclient=smtplib.SMTP('127.0.0.1',8001)
smtpClient.sendmail('sender#gmail.com','recivers#gmail.com','sadfsdf')

Related

Using GLib.IOChannel to send data from one python process to another

I am trying to use GLib.IOChannels to send data from a client to a server running a Glib.Mainloop.
The file used for the socket should be located at /tmp/so/sock, and the server should simply run a function whenever it receives data.
This is the code I've written:
import sys
import gi
from gi.repository import GLib
ADRESS = '/tmp/so/sock'
def server():
loop = GLib.MainLoop()
with open(ADRESS, 'r') as sock_file:
sock = GLib.IOChannel.unix_new(sock_file.fileno())
GLib.io_add_watch(sock, GLib.IO_IN,
lambda *args: print('received:', args))
loop.run()
def client(argv):
sock_file = open(ADRESS, 'w')
sock = GLib.IOChannel.unix_new(sock_file.fileno())
try:
print(sock.write_chars(' '.join(argv).encode('utf-8'), -1))
except GLib.Error:
raise
finally:
sock.shutdown(True)
# sock_file.close() # calling close breaks the script?
if __name__ == '__main__':
if len(sys.argv) > 1:
client(sys.argv[1:])
else:
server()
When called without arguments, it acts as the server, if called with arguments, it sends them to a running server.
When starting the server, I immediately get the following output:
received: (<GLib.IOChannel object at 0x7fbd72558b80 (GIOChannel at 0x55b8397905c0)>, <flags G_IO_IN of type GLib.IOCondition>)
I don't know why that is. Whenever I send something, I get an output like (<enum G_IO_STATUS_NORMAL of type GLib.IOStatus>, bytes_written=4) on the client side, while nothing happens server-side.
What am I missing? I suspect I understood the documentation wrong, as I did not find a concrete example.
I got the inspiration to use the IOChannel instead of normal sockets from this post: How to listen socket, when app is running in gtk.main()?

RPyC Client to Client send message freeze

I'm trying to send a message from a client to another client using RPyC.
For the moment I use the following code, I launch the server first then I connect and "register" clients to the server ( I could've done that to the on_connect() method too ... but doesn't change anything as far as I see).
Any advise or help much appreciated, thanks !
To register the clients I do this:
On one shell (client1 => light ):
import h_client
c = h_client._connectToServer()
c.root.registerClient("light")
On Another shell (client2 => dark ):
import h_client
c = h_client._connectToServer()
c.root.registerClient("dark")
c.root.sendDataToClient("light", "msg", "me", "My great message")
The script freezes until I go back to the "light" shell and write something ( like c.root ... ), and then I can see the result on my "light" shell, if I do nothing in the shell it seems that the result never shows up..
Server (h_server.py):
import rpyc
from rpyc.utils.server import ThreadedServer
class HChat_Server(rpyc.Service):
CLIENTS = {}
def exposed_registerClient(self, clientID):
self.CLIENTS[clientID] = self._conn.root.exposed_catchData
def exposed_getAllClients(self):
return self.CLIENTS
def exposed_sendDataToClient(self, clientID, dataType, sender, data):
self.CLIENTS[clientID](dataType, sender, data)
if __name__ == "__main__":
t = ThreadedServer(HChat_Server, port = 5000, protocol_config={"allow_public_attrs" : True})
t.start()
Client (h_client.py):
class HChat_ClientService(rpyc.Service):
def exposed_catchData(self, dataType, sender, data):
sys.stdout.write("=> {0}: {1} ({2})".format(sender, data, dataType))
def _connectToServer():
server_conn = rpyc.connect("localhost", 5000, service=HChat_ClientService)
return server_conn

How to handle TCP connection events in order to call methods within other class?

I am creating a robot which is going to be driven by the commands received over TCP connection. Therefore, I will have a robot class with methods (e.g. sense(), drive()...) and the class for TCP connection.
To establish TCP connection, I looked at examples from twisted. On the client side, I have written a client.py script for connection handling:
from twisted.internet import reactor, protocol
import random
from eventhook import EventHook
import common
#from Common.socketdataobjects import response
# a client protocol
class EchoClient(protocol.Protocol):
"""Once connected, send a message, then print the result."""
def connectionMade(self):
self.transport.write("hello, world!")
#the server should be notified that the connection to the robot has been established
#along with robot state (position)
#eventConnectionEstablishedHook.fire()
def dataReceived(self, data):
print "Server said:", data
self.transport.write("Hello %s" % str(random.randint(1,10)))
'''
serverMessage = common.deserializeJson(data)
command = serverMessage.command
arguments = serverMessage.arguments
#here we get for example command = "DRIVE"
#arguments = {motor1Speed: 50, motor2Speed: 40}
instead of above response, used for testing purposes,
the commands should be extracted from the data and according to the command,
the method in Robot instance should be called.
When the command execution finishes, the self.transport.write() method should be called
to notify the server that the command execution finished
'''
def connectionLost(self, reason):
print "connection lost"
class EchoFactory(protocol.ClientFactory):
protocol = EchoClient
def clientConnectionFailed(self, connector, reason):
print "Connection failed - goodbye!"
reactor.stop()
def clientConnectionLost(self, connector, reason):
print "Connection lost - goodbye!"
reactor.stop()
# this connects the protocol to a server runing on port 8000
def initializeEventHandlers(connectionEstablishedHook):
global connection
connection.established = 0
global eventConnectionEstablishedHook
eventConnectionEstablishedHook = connectionEstablishedHook
def main():
f = EchoFactory()
reactor.connectTCP("localhost", 8000, f)
reactor.run()
# this only runs if the module was *not* imported
if __name__ == '__main__':
main()
Beside this script, I have a robot class:
Class Robot(object():
def __init(self)__:
self.position = (0,0)
def drive(self, speedMotor1, speedMotor2, driveTime)
updateMotor1State(speedMotor1)
updateMotor2State(speedMotor2)
time.sleep(driveTime)
#when the execution finished, the finish status should be sent to client in order to inform the server
return "Finished"
def sense(self)
#logic to get the data from the environment
What I would like to do, is to receive the data(commands) from TCP connection and then call the according method in Robot instance. Some procedures might take longer (e.g. driving), so I tried to use events, but haven't figured out the appropriate way to communicate between TCP client and robot using events:
if __name__ == '__main__':
robotController = Robot()
eventController = Controller()
connectionEstablishedHook = EventHook()
client.initializeEventHandlers(connectionEstablishedHook)
eventController.connection = connectionEstablishedHook
client.main()
I tried to create ClientMainProgram script, where I wanted to create an instance of a robot, an instance of TCP client and implement the communication between them using events.
Previously I have managed to implement event handling using Michael Foord's events pattern on a simpler example. I would be very thankful if anyone could provide the solution to this question or any similar example which might be helpful to solve this problem.
Events are easily represented using regular Python function calls.
For example, if your protocol looks like this:
from twisted.internet.protocol import Protocol
class RobotController(Protocol):
def __init__(self, robot):
self.robot = robot
def dataReceived(self, data):
for byte in data:
self.commandReceived(byte)
def commandReceived(self, command):
if command == "\x00":
# drive:
self.robot.drive()
elif command == "\x01":
# sense:
self.robot.sense()
...
(The specifics of the protocol used in this example are somewhat incidental. I picked this protocol because it's very simple and has almost no parsing logic. For your real application I suggest you use twisted.protocols.amp.)
Then all you need to do is make sure the robot attribute is properly initialized. You can do this easily using the somewhat newer endpoint APIs that can often replace use of factories:
from sys import argv
from twisted.internet.endpoints import clientFromString, connectProtocol
from twisted.internet.task import react
def main(reactor, description):
robot = ...
endpoint = clientFromString(reactor, description)
connecting = connectProtocol(endpoint, RobotController(robot))
def connected(controller):
...
connecting.addCallback(connected)
return connecting
react(main, argv[1:])

Howto connect two programs with Twisted

I have an echoserver in Twisted that needs to get input from an echoclient. The echocient is a GUI (Panda3D). The client just sends a short message when a button is clicked.
So I have messages to send at irregular times (only when button is clicked).
How can I have a permanent connection (the reactor.run() is already started at the beginning of the client program) and send messages.
I don't want to write a polling mechanism in EchoClient/connectionMade. I saw an example of gtk+ but cannot translate it to Panda. How to go about. The code hereunder is not working at all but gives you an idea of what I want (basically permanent connection and once in a while the user sends something when pressing a button).
from direct.showbase.ShowBase import ShowBase
from direct.gui.DirectButton import DirectButton
from panda3d.core import Vec3
from direct.task import Task
from twisted.internet import protocol, reactor, defer
from twisted.internet.task import LoopingCall
from twisted.spread import pb
FRAMERATE = 32
class LoginDialog:
def __init__(self, deferred):
self.deferredResult = deferred
class EchoClient(ShowBase, protocol.Protocol):
def __init__(self):
ShowBase.__init__(self)
self.echoer = echoer
self.button = DirectButton(pos = Vec3(.1,0,.1), text = "Send request",
scale = .1, pad = (.5, .5),
rolloverSound = None, clickSound = None,
command = self.Request)
def Request():
self.echoer.transport.write("Message from client")
def dataReceived(self, data):
print "Server said: ", data
cf = pb.PBClientFactory()
cf.getRootObject().addCallback(EchoClient)
reactor.connectTCP("localhost", 17000, cf)
LoopingCall(taskMgr.step).start(1 / FRAMERATE)
reactor.run()
If you make the client and the server part of the same process then you'll always (well, practically always) be able to pass information from one to the other.
If you make the client and the server different processes then there is probably no solution that satisfies your requirements.
You always have to do something to establish a connection between two processes and there's always a chance it might go away. Sorry.
have a look at multiprocessing: http://docs.python.org/2/library/multiprocessing.html
you can start and join different processes as well as message between them.
I found the answer. Now I have a program that sends a message to a server once a button is pushed. I used a ClientCreator to create an EchoClient. Like this:
self.clientcreate = protocol.ClientCreator(reactor, EchoClient)
self.clientcreate.connectTCP(host, port).addCallbacks(self.connectionMade,
self.connectionFailed)
Now when I connectTCP, and make a connection it calls self.ConnectionMade upon success.
Thereby it also gives the EchoClient to the function. So I can store it (self.client = echoclient), and use it when I want (could not achieve this via Factories).
For instance the button calls the function Request and there I can directly use the transport.write command, because I have the client now. So self.client.transport.write('whatever').
If people did not understand what I wanted before, have better ideas to get this done, I would like to see their comments (i want to learn).
The complete code (Client only):
from twisted.internet import protocol, reactor, defer
from twisted.internet.task import LoopingCall
from direct.showbase.ShowBase import ShowBase
from direct.gui.DirectButton import DirectButton
from panda3d.core import Vec3
from direct.task import Task
FRAMERATE = 32
class ButtonDialog(ShowBase):
def __init__(self):
ShowBase.__init__(self)
self.button = DirectButton(pos = Vec3(.1,0,.1), text = "Send request",
scale = .1, pad = (.5, .5),
rolloverSound = None, clickSound = None,
command = self.Request)
host = "localhost"
port = 17001
self.clientcreate = protocol.ClientCreator(reactor, EchoClient)
self.clientcreate.connectTCP(host, port).addCallbacks(self.connectionMade,
self.connectionFailed)
def connectionFailed(self, f):
print "Connection Failed:", f
reactor.stop()
def connectionMade(self, echoclient):
self.client = echoclient
def Request(self):
self.client.transport.write("Message from button")
class EchoClient(protocol.Protocol):
def dataReceived(self, data):
print "Server said: ", data
def connectionLost(self, err):
print "Connection is lost: " + str(err)
reactor.stop()
ButtonDialog()
LoopingCall(taskMgr.step).start(1 / FRAMERATE)
reactor.run()

Simple continuously running XMPP client in python

I'm using python-xmpp to send jabber messages. Everything works fine except that every time I want to send messages (every 15 minutes) I need to reconnect to the jabber server, and in the meantime the sending client is offline and cannot receive messages.
So I want to write a really simple, indefinitely running xmpp client, that is online the whole time and can send (and receive) messages when required.
My trivial (non-working) approach:
import time
import xmpp
class Jabber(object):
def __init__(self):
server = 'example.com'
username = 'bot'
passwd = 'password'
self.client = xmpp.Client(server)
self.client.connect(server=(server, 5222))
self.client.auth(username, passwd, 'bot')
self.client.sendInitPresence()
self.sleep()
def sleep(self):
self.awake = False
delay = 1
while not self.awake:
time.sleep(delay)
def wake(self):
self.awake = True
def auth(self, jid):
self.client.getRoster().Authorize(jid)
self.sleep()
def send(self, jid, msg):
message = xmpp.Message(jid, msg)
message.setAttr('type', 'chat')
self.client.send(message)
self.sleep()
if __name__ == '__main__':
j = Jabber()
time.sleep(3)
j.wake()
j.send('receiver#example.org', 'hello world')
time.sleep(30)
The problem here seems to be that I cannot wake it up. My best guess is that I need some kind of concurrency. Is that true, and if so how would I best go about that?
EDIT: After looking into all the options concerning concurrency, I decided to go with twisted and wokkel. If I could, I would delete this post.
There is a good example on the homepage of xmpppy itself (which is another name for python-xmpp), which does almost what you want: xtalk.py
It is basically a console jabber-client, but shouldn't be hard to rewrite into bot you want.
It's always online and can send and receive messages. I don't see a need for multiprocessing (or other concurrency) module here, unless you need to receive and send messages at exact same time.
A loop over the Process(timeout) method is a good way to wait and process any new incoming stanzas while keeping the connection up.

Categories

Resources