I have sleekXMPP for python and I have used the API to create functions to send messages, although when I researched into receiving them I can't find anything, can someone please help me to work this out, or disprove the possibility. Thanks.
Below is the code I used to send Messages, If its any help.
to = config.get('usermap', to[4:])
gmail_from_user = config.get('auth', 'email')
gmail_from_secret = config.get('auth', 'secret')
sys.stdout = stdouttmp
sys.stderr = stderrtmp
print "Sending chat message to " + to
xmpp = SendMsgBot(gmail_from_user, gmail_from_secret, to, message)
xmpp.register_plugin('xep_0030') # Service Discovery
xmpp.register_plugin('xep_0199') # XMPP Ping
sys.stdout = stdouttmp
if xmpp.connect(('talk.google.com', 5222)):
xmpp.process(block=True)
else:
sys.stdout = stdouttmp
print("Unable to connect.")
sys.stdout = stdouttmp
sys.stderr = stderrtmp
btw I'm using a .cfg text file for the users email and password, along with some contacts, which is then parsed in
I see that you're using the send_client.py example. The intent of that example is how to reliably log in, send a single message, and then log out. Your use case is to both send and receive messages, so you would be better served looking at the echo_client.py example.
Notably, in order to receive a message you would do:
# in your __init__ method:
def __init__(...):
# ...
self.add_event_handler('message', self.recv_message)
def recv_message(self, msg):
# You'll probably want to ignore error and headline messages.
# If you want to handle group chat messages, add 'groupchat' to the list.
if msg['type'] in ('chat', 'normal'):
print "%s says: %s" % (msg['from'], msg['body'])
Again, you will need to switch from using the SendMsgBot example because it automatically disconnects after sending its message.
Don't forget that there is the sleek#conference.jabber.org chat room if you need any help.
-- Lance
Related
I am creating a reference bot for chatting in VK in Python using the Callback Api. The bot works correctly if you write to the group messages. However, if you write to a conversation (to which the bot is added), it replies to private messages. All rights to read, etc. issued. As I understand it (studying information on the internet), I use user_id, not chat_id. But I didn't understand how to fix it correctly (
p.s. It is advisable that the bot write both in private messages and in a conversation, depending on where they ask.
p.p.s perhaps the question seems ridiculous, but I just started to study this area, and I did not find the answer on the net :-)
The bot itself:
import vk
import random
import messageHandler
# app.route ('/', methods = ['POST'])
def processing ():
data = json.loads (request.data)
if 'type' not in data.keys ():
return 'not vk'
if data ['type'] == 'confirmation':
return confirmation_token
elif data ['type'] == 'message_new':
messageHandler.create_answer (data ['object'] ['message'], token)
return 'ok'
"Responder":
import importlib
from command_system import command_list
def load_modules ():
# path from the working directory, it can be changed in the application settings
files = os.listdir ("mysite / commands")
modules = filter (lambda x: x.endswith ('. py'), files)
for m in modules:
importlib.import_module ("commands." + m [0: -3])
def get_answer (body):
# Default message if unrecognizable
message = "Sorry, I don't understand you. Write '/ help' to see my commands."
attachment = ''
for c in command_list:
if body in c.keys:
message, attachment = c.process ()
return message, attachment
def create_answer (data, token):
load_modules ()
user_id = data ['from_id']
message, attachment = get_answer (data ['text']. lower ())
vkapi.send_message (user_id, token, message, attachment)
I don't speak English well, so I apologize for the crooked translation)
Use Peer_id, instead of from_id. (data->object->peer_id)
(i used php, but i had a similar problem. this is the solution)
probably something like this:
def create_answer (data, token):
load_modules ()
user_id = data ['peer_id'] # id source edited
message, attachment = get_answer (data ['text']. lower ())
vkapi.send_message (user_id, token, message, attachment)
from_id - person who sent the message
peer_id - in which dealogue message was received. (for groups it looks like 20000005)
So, you will send the message to conversation (does not matter is this PM or conversation with a lot of people)
We're currently using a super basic Python script that I found online a while ago to send an error report via HTML from out departmental email address. However, as it currently stands, it sends the email from our email address to our email address. I'm hoping there might be some way to send the email from the address of the current user. Here's what we've got:
def sendMail(sender, recipient, subject, html, text):
import MimeWriter, mimetools, cStringIO
import smtplib
out = cStringIO.StringIO()
htmlin = cStringIO.StringIO(html)
txtin = cStringIO.StringIO(text)
writer = MimeWriter.MimeWriter(out)
writer.addheader("From", sender)
writer.addheader("To", recipient)
writer.addheader("Subject", subject)
writer.addheader("MIME-Version", "1.0")
writer.startmultipartbody("alternative")
writer.flushheaders()
subpart = writer.nextpart()
subpart.addheader("Content-Transfer-Encoding", "quoted-printable")
pout = subpart.startbody("text/plain", [("charset", 'us-ascii')])
mimetools.encode(txtin, pout, 'quoted-printable')
txtin.close()
subpart = writer.nextpart()
subpart.addheader("Content-Transfer-Encoding", "quoted-printable")
pout = subpart.startbody("text/html", [("charset", 'us-ascii')])
mimetools.encode(htmlin, pout, 'quoted-printable')
htmlin.close()
writer.lastpart()
msg = out.getvalue()
server = smtplib.SMTP('smtp.office365.com',587)
server.ehlo()
server.starttls()
server.ehlo()
server.login("sample#email.com","sample")
server.sendmail(sender, recipient, msg)
server.quit()
Then we're using a simple try/except execfile script to run everything from:
try:
execfile('\\\\path.py')
except:
print 'ATTENTION: An error has been detected in a script process.'
traceback.print_exc(file=sys.stdout)
import sys, cgitb
recipient =
['sample#email.com','sample2#email.com','sample3#email.com','sample4#email.com']
for rec in recipient:
Utils.sendMail('sample#email.com',
rec,
'ATTENTION: An error has been detected in a script process...',
cgitb.html(sys.exc_info()),
cgitb.text(sys.exc_info()))
sys.exit()
It's here where we define the address we're sending to:
for rec in recipient:
Utils.sendMail('sample#email.com',
rec,
'ATTENTION: An error has been detected in a script process...',
cgitb.html(sys.exc_info()),
cgitb.text(sys.exc_info()))
sys.exit()
Is there some kind of AD script we can implement here? We've got about 30 people using our processes so whenever an error pops up all we get is an email with the error and no reference to who it belongs to.
It is not easy to work with AD in Python, and it's even tougher to do without installing any 3rd party modules.
Would adding the username that ran the script in the email body or subject suffice instead?:
import getpass
user = getpass.getuser()
Then in the execfile script:
Utils.sendMail(
'sample#email.com',
rec,
'ATTENTION: %s has run a script which has errored...' % user,
cgitb.html(sys.exc_info()),
cgitb.text(sys.exc_info())
)
It is important to note that this should not be used for any legitimate authentication purposes, as it does not protect against user-spoofing and the likes..
Sounds like you need to group you recipients i.e. you could have a group for engineers, quality assurance, business development, management, etc..
where each group is represented by a list of email addresses.
This way when an error occurs, you may send a human readable email describing the issue to the quality assurance group.
As for the engineers, you may want to send a more technical email that not only contains the human readable error descriptions, but also an additional stack trace. When an engineer is attempting to troubleshoot an error message more, is better.
As for the business development and management group, they probably shouldn't be receiving emails on failures.
hope that helps.
I want to use SleekXMPP and automatically accept all chat room invites that are sent to me. I know that the xep_0045 plugin can detect when I receive an invite, as I am notified in the debugger. I am still pretty new to Python and any help would be appreciated.
So far, I've found a function called handle_groupchat_invite in the xep_0045 plugin. Specifically, this code:
def plugin_init(self):
#...
self.xmpp.registerHandler(Callback('MUCInvite', MatchXMLMask("<message xmlns='%s'><x xmlns='http://jabber.org/protocol/muc#user'><invite></invite></x></message>" % self.xmpp.default_ns), self.handle_groupchat_invite))
#...
def handle_groupchat_invite(self, inv):
""" Handle an invite into a muc.
"""
logging.debug("MUC invite to %s from %s: %s", inv['from'], inv["from"], inv)
if inv['from'].bare not in self.rooms.keys():
self.xmpp.event("groupchat_invite", inv)
So I see this method at work as I see the "MUC invite to..." message in the Terminal log. From there, I would expect that I need to use self.plugin['xep_0045'].joinMUC() to join the chat room's URL (given by inv["from"]). However, I am not exactly sure where I should call this code in my script.
Thanks again for the help.
Update: I've also tried using add_event_handler in the __init__ function. Specifically my code is:
def __init__(self, jid, password, room, nick):
sleekxmpp.ClientXMPP.__init__(self, jid, password)
self.room = room
self.nick = nick
# The session_start event will be triggered when
# the bot establishes its connection with the server
# and the XML streams are ready for use. We want to
# listen for this event so that we we can initialize
# our roster.
self.add_event_handler("session_start", self.start)
# The groupchat_message event is triggered whenever a message
# stanza is received from any chat room. If you also also
# register a handler for the 'message' event, MUC messages
# will be processed by both handlers.
self.add_event_handler("groupchat_message", self.muc_message)
# The groupchat_presence event is triggered whenever a
# presence stanza is received from any chat room, including
# any presences you send yourself. To limit event handling
# to a single room, use the events muc::room#server::presence,
# muc::room#server::got_online, or muc::room#server::got_offline.
self.add_event_handler("muc::%s::got_online" % self.room,
self.muc_online)
self.add_event_hander("groupchat_invite", self.sent_invite)
From there, I created the sent_invite function, code is here:
def sent_invite(self, inv):
self.plugin['xep_0045'].joinMUC(inv["from"], self.nick, wait=True)
However, I get the following error when I do this:
File "muc.py", line 66, in init
self.add_event_hander("groupchat_invite", self.sent_invite) AttributeError: 'MUCBot' object has no attribute 'add_event_hander'
Yet in the xep_0045 plugin I see this code: self.xmpp.event("groupchat_invite", inv). According to the Event Handlers SleekXMPP wiki page,
Stream events arise whenever particular stanzas are received from the XML stream. Triggered events are created whenever xmpp.event(name, data) is called (where xmpp is a SleekXMPP object).
Can someone please explain why I am getting the error? I've also tried using
self.add_event_hander("muc::groupchat_invite", self.sent_invite)
but also without success.
I just downloaded SleekXMPP from git and add groupchat_invite handler like this and it works:
diff --git a/examples/muc.py b/examples/muc.py
index 5b5c764..e327fac 100755
--- a/examples/muc.py
+++ b/examples/muc.py
## -61,7 +61,10 ## class MUCBot(sleekxmpp.ClientXMPP):
# muc::room#server::got_online, or muc::room#server::got_offline.
self.add_event_handler("muc::%s::got_online" % self.room,
self.muc_online)
-
+ self.add_event_handler("groupchat_invite", self.accept_invite)
+
+ def accept_invite(self, inv):
+ print("Invite from %s to %s" %(inv["from"], inv["to"]))
def start(self, event):
"""
I'm trying to subscribe to a tag. It appears that the callback URL is being called correctly with a hub.challenge and hub.mode, and I figured out how to access the challenge using self.request.get('hub.challenge'). I thought I was just supposed to echo the challenge, but that doesn't appear to work since I receive the following errors in the GAE logs:
InstagramAPIError: (400) APISubscriptionError-Challenge verification failed. Sent "647bf6dbed31465093ee970577ce1b72", received "
647bf6dbed31465093ee970577ce1b72
".
Here is the full handler:
class InstagramHandler(BaseHandler):
def get(self):
def process_tag_update(update):
update = update
mode = self.request.get('hub.mode')
challenge = self.request.get('hub.challenge')
verify_token = self.request.get('hub.verify_token')
if challenge:
template_values = {'challenge':challenge}
path = os.path.join(os.path.dirname(__file__), '../templates/instagram.html')
html = template.render(path, template_values)
self.response.out.write(html)
else:
reactor = subscriptions.SubscriptionsReactor()
reactor.register_callback(subscriptions.SubscriptionType.TAG, process_tag_update)
x_hub_signature = self.request.headers.get('X-Hub-Signature')
raw_response = self.request.data
try:
reactor.process('INSTAGRAM_SECRET', raw_response, x_hub_signature)
except subscriptions.SubscriptionVerifyError:
logging.error('Instagram signature mismatch')
So returning it as a string worked. I should have payed closer attention to the error message, but it took a helpful person on the Python IRC to point out the extra line breaks in the message. Once I put the template files on one line, it seemed to work. I can now confirm that my app is authorized via Instagram's list subscription URL.
Our office uses 2 IMAP servers for e-mail, one is the incoming server and holds the recent e-mails and the other is an archive server. We mainly use Outlook 2010 and our current process is to periodically drag sent messages from the incoming server to the archive.
Today I was asked into looking into writing a script and that would periodically (probably using crontab) grab all sent messages and move them to archive.
I've looked into some example of SSL or telnet to access the server and poke around. However I don't know the best way to script this or how to move files cross server within the IMAP environment.
What's the best way to accomplish this? I'd prefer to use Python just from comfort level, but if there is already an existing solution in another language, I could deal with it.
Update:
Ok, here's some code. Currently It copies the messages just fine, however, it will duplicate exisiting messages on the archive server.
import imaplib
import sys
#copy from
f_server = 'some.secret.ip.address'
f_username = 'j#example.com'
f_password = 'password'
f_box_name = 'Sent Messages'
#copy to
t_server = 'archive.server.i.p'
t_username = 'username'
t_password = 'password'
t_box_name = 'test'
To = imaplib.IMAP4(t_server)
To.login(t_username, t_password)
print 'Logged into mail server'
From = imaplib.IMAP4(f_server)
From.login(f_username, f_password)
print 'Logged into archive'
From.select(f_box_name) #open box which will have its contents copied
print 'Fetching messages...'
typ, data = From.search(None, 'ALL') #get all messages in the box
msgs = data[0].split()
sys.stdout.write(" ".join(['Copying', str(len(msgs)), 'messages']))
for num in msgs: #iterate over each messages id number
typ, data = From.fetch(num, '(RFC822)')
sys.stdout.write('.')
To.append(t_box_name, None, None, data[0][1]) #add a copy of the message to the archive box specified above
sys.stdout.write('\n')
try:
From.close()
From.logout()
try:
To.close()
To.logout()
Some sources:
Doug Hellman's Blog: imaplib - IMAP4 Client Library
Tyler Lesmann's Blog: Copying IMAP Mailboxes with Python and imaplib
I still need to:
delete/expunge messages on the live server
not copy duplicates (actually this would be fixed by deleting originals after copying, but...)
error trapping
Update 2:
Anyone have any ideas on how to not create duplicates when copying? (excluding the option of deleting originals, for now) I thought about searching text, but realized nested replies could throw that off.
Here's what I ended up using. I don't claim that it's perfect, the way it uses msg_num and not id is a little risky. But this is fairly low volume moves, maybe a couple an hour (on cron).
import imaplib
#copy from
from_server = {'server': '1.1.1.1',
'username': 'j#example.com',
'password': 'pass',
'box_names': ['Sent', 'Sent Messages']}
#copy to
to_server = {'server': '2.2.2.2',
'username': 'archive',
'password': 'password',
'box_name': 'Sent'}
def connect_server(server):
conn = imaplib.IMAP4(server['server'])
conn.login(server['username'], server['password'])
print 'Logged into mail server # %s' % server['server']
return conn
def disconnect_server(server_conn):
out = server_conn.logout()
if __name__ == '__main__':
From = connect_server(from_server)
To = connect_server(to_server)
for box in from_server['box_names']:
box_select = From.select(box, readonly = False) #open box which will have its contents copied
print 'Fetching messages from \'%s\'...' % box
resp, items = From.search(None, 'ALL') #get all messages in the box
msg_nums = items[0].split()
print '%s messages to archive' % len(msg_nums)
for msg_num in msg_nums:
resp, data = From.fetch(msg_num, "(FLAGS INTERNALDATE BODY.PEEK[])") # get email
message = data[0][1]
flags = imaplib.ParseFlags(data[0][0]) # get flags
flag_str = " ".join(flags)
date = imaplib.Time2Internaldate(imaplib.Internaldate2tuple(data[0][0])) #get date
copy_result = To.append(to_server['box_name'], flag_str, date, message) # copy to archive
if copy_result[0] == 'OK':
del_msg = From.store(msg_num, '+FLAGS', '\\Deleted') # mark for deletion
ex = From.expunge() # delete marked
print 'expunge status: %s' % ex[0]
if not ex[1][0]: # result can be ['OK', [None]] if no messages need to be deleted
print 'expunge count: 0'
else:
print 'expunge count: %s' % len(ex[1])
disconnect_server(From)
disconnect_server(To)
I'm not sure what volume of messages you're dealing with, but you could extract the Message-ID from each one and use that to find out if it's a duplicate. Either generate a list of IDs already on the target server each time you prepare to move messages, or add them to a simple database as they are archived.
You could narrow things down by an additional message property like Date if the lookups are too expensive, then drop the older lists when you no longer need them.
Presumably too late to be helpful to the OP, but hopefully useful for anyone following along after now.
This looks like a generic requirement. You probably shouldn't be custom coding anything.
You would probably be better off using an MTA configured to send copies of everything to an archive as well as sending stuff to your IMAP server. If this is hard for you to set up, consider using a third party service, who would manage your archives, and forward mail on to your existing mail server.
If you really do want to do this by copying from IMAP, I'd suggest looking at offlineimap.
If you really do want to do it yourself, the way to track the messages you've already seen is by using the Message-ID header.