How to update email with BAPI_USER_CHANGE in pyrfc? - python

I was able to write the code to get the details from SAP thru BAPI_USER_GET_DETAIL, here is attached code to get the email from SAP backend:
import pyrfc
from pyrfc import Connection
setup= pyrfc.Connection(user=X , passwd=Y , mshost=Z , sysid=A , client=B , msserv= C , group=D )
result=setup.call(BAPI_USER_GET_DETAIL, USERNAME=abc)
print (result['ADDRESS']['E_MAIL'])
Expected Result: abc#xyz.com
I am in need to update email address for particular user in SAP, after researching found that by using BAPI_USER_CHANGE we can update new mail address but tried many times with no luck!
Can anyone please help in getting the correct syntax to run BAPI_USER_CHANGE in Python?

First of all, your get BAPI is also a bit of incorrect, maybe on old versions of PyRFC it worked but now pyrfc module has Connection object, not connection and your code throws compilation error. It should be as follows:
import pyrfc
from pyrfc import Connection
RIS=pyrfc.Connection(user='USER', passwd='pw', ashost='hostey.com', sysid='KEK', sysnr='00', client='200', lang='EN', trace='3')
result=RIS.call("BAPI_USER_GET_DETAIL", USERNAME='MUELLER')
print(result['ADDRESS']['FULLNAME'])
Secondly, change BAPI is called the same as get BAPI, for me this code worked
ADDR = { "E_MAIL": 'wazawaza#mail.com'}
ADDX = { "E_MAIL": 'X'}
changed=RIS.call("BAPI_USER_CHANGE", USERNAME='MUELLER', ADDRESS=ADDR, ADDRESSX=ADDX)
print(changed["RETURN"])
it should show you smth like this output if executed correctly
[{'TYPE': 'S', 'ID': '01', 'NUMBER': '039', 'MESSAGE': 'User MUELLER has changed', 'LOG_NO': '', 'LOG_MSG_NO': '000000', 'MESSAGE_V1': 'MUELLER', 'MESSAGE_V2': '', 'MESSAGE_V3': '', 'MESSAGE_V4': '', 'PARAMETER': '', 'ROW': 0, 'FIELD': 'BNAME', 'SYSTEM': 'T90CLNT090'}]
Weirdly new email does not showed neither with BAPI call nor in SE37, but perfectly showed in SU01.
I thinks this is because of the long char field in BAPI structure which prevents it from showing correctly. Maybe this was the reason why you considered your call unsuccessful?

For any "Update BAPI" you need to call BAPI_TRANSACTION_COMMIT right after your BAPI call in order to actually commit the changes to the database.
Make sure the BAPI_TRANSACTION_COMMIT is executed on the same "connection", because it needs to run in the same backend user session.

Related

JIRA API - Python Lib - Create_Issue - Option id 'null' is not valid

So my issue is with the Python Library for the JIRA API. We are using JIRA as a asset management database (Yes I know its normal used by dev's and we use it for that as well but this was a case were it worked well) to keep track of are server configs (Memory, CPU, Location on the Rack ..etc..)
Using this function I am having it create a Issue under a Project and pull the information for the fields from another API.
(note that I cant give clues as to who I work for so the code is edited - however it all works expect when i add one line)
def create_compute_node_in_jira(self, compute_node_name ,user_name, password, info_dic):
help_obj = helper()
jira = JIRA("https://",basic_auth=(user_name,password))
#Uses a dic to create the fields / info for the Issue
issue_dict = {
'project': {'key': <project>},
'summary': compute_node_name,
'issuetype': {'name': 'Server Hardware'},
'customfield_10500': str(info_dic["Hostname"]),
'customfield_11007': {'value': str("2U")},
'customfield_11006': str(info_dic["Aggr0-IP"]),
'customfield_10510': {'value': str(7)},
'customfield_10501': str(info_dic["Serial-Number"])
'customfield_10502': {'value': str(<server>)},
'customfield_10503': str(help_obj.data_parser_sm(info_dic["Hostname"])),
'customfield_10509': {'value': str("<OS>")},
'customfield_10504': {'value': str("<mem>")},
'customfield_10505': str(help_obj.data_parser_cpu(info_dic["CpuType"])),
'customfield_10507': {'value': str(info_dic["Cpu-Core"])},
'customfield_10508': {'value': str(<OS Version>)},
'customfield_11008': {'value': str("CMH")}
}
jira.create_issue(fields=issue_dict)
return "[*]Created ticket" # Should exit script after this is returned
The line - 'customfield_11008': {'value': str("CMH")} - causes the function to return the following expection:
jira.utils.JIRAError: JiraError HTTP 400
text: Option id 'null' is not valid
url: https:///rest/api/2/issue
however when i omit that line it runs with out a problem. I tried CMH lower case - capital ..etc.. and it still breaks the scripts. I even went through the web gui and copied the "CMH" entry in another ticket and it stilled caused a problem. Has anybody seen this before / have any guesses as to why it is breaking ?
So after a while of playing around with JIRA I found out it was my own mistake. It seems this error is caused when you post to a field using the API a "value" that it does not understand. A example was I was using the wrong custom field and the JIRA Field that I was posting to was not setup to take the value I was using.
You will see this error when the field's value is expected to match an option list, and you are trying to send a value which is not on this list.

How to bind (authenticate) a user with ldap3 in python3

I'm trying to update some code to python3, using ldap3 version '0.9.7.4'.
(https://pypi.python.org/pypi/ldap3)
Previously, I used python-ldap with python2 to authenticate a user like this:
import ldap
address = "ldap://HOST:389"
con = ldap.initialize(address)
base_dn = "ourDN=jjj"
con.protocol_version = ldap.VERSION3
search_filter = "(uid=USERNAME)"
result = con.search_s(base_dn, ldap.SCOPE_SUBTREE, search_filter, None)
user_dn = result[0][0] # get the user DN
con.simple_bind_s(user_dn, "PASSWORD")
This properly returns (97, [], 2, []) on correct password, and raises ldap.INVALID_CREDENTIALS on a bind attempt using an incorrect password.
Using ldap3 in python3 I'm doing the following:
from ldap3 import Server, Connection, AUTH_SIMPLE, STRATEGY_SYNC, ALL
s = Server(HOST, port=389, get_info=ALL)
c = Connection(s, authentication=AUTH_SIMPLE, user=user_dn, password=PASSWORD, check_names=True, lazy=False, client_strategy=STRATEGY_SYNC, raise_exceptions=True)
c.open()
c.bind()
It's raising the following exception:
ldap3.core.exceptions.LDAPInvalidCredentialsResult: LDAPInvalidCredentialsResult - 49 - invalidCredentials - [{'dn': '', 'message': '', 'type': 'bindResponse', 'result': 0, 'saslCreds': 'None', 'description': 'success', 'referrals': None}]
I'm using the user_dn value returned by python2's ldap search, since this appears to be working in python2.
How can I get this to bind properly using ldap3 in python3?
(One thing strange, I noticed, is that the ldap3's LDAPInvalidCredentialsResult includes 'description': 'success'. I'm guessing this just means response successfully recieved...)
I'm the author of ldap3, please set raise_exceptions=False in the Connection definition and check the connection.result after the bind. You should get the reason why your bind() is unsuccessful.
Confirm that your DN doesn't need to escape a comma using backslash \.
My organization gives users a CN of "last name, first name", so my DN needed to be "CN=Doe\, Jane, OU=xyz, ..., DC=abc, DC=com"
I realized this by using Active Directory Explorer to navigate to my user object, r-click > view properties to see the distinguished name. I ran into this invalid credential error when using the DN that AD Explorer displays in its Path breadcrumb which omits the escape character.

What is the proper way to set the "From" header in an email using Django EmailMessage class?

I'm able to send an email and set most headers with no problem.
But this has been giving me odd results for quite some time now.
This is where I'm currently at:
email = EmailMessage(
'My foobar subject!!',
render_to_string(
'emails/new_foobar_email.txt',
{
'foo': foo.something,
'bar': bar.something,
}
),
'notify#foobar.com',
[the_user.email, ],
headers={'From ': 'Darth Vader <darth#vader.com>'},
)
email.send(
fail_silently=False
)
When the email arrives, it says it is from "notify#foobar.com" and not "Darth Vader".
I've tried setting the headers like this:
# this way worked but was inconsistent. Some email clients showed it was from "unknown sender".
headers={'From ': 'Darth Vader'},
I've dug through this document about Internet Message Formats (RFC 2822) and it wasn't clear to me if I was following the best practice.
I also saw this SO Question, but it applies to the send_mail() function. It could be similar but it is different.
I'm not concerned with my email client displaying correctly (it could be tainted since I've been trying so many different ways and probably cached one of the ways that I was doing wrong..) but I'm concerned with following best practices so it will work for the majority of email clients.
Question
What is the proper way to set the "From" header in an email using EmailMessage class? And, what is the most compatible way with email clients?
You can put the details directly in the from argument:
email = EmailMessage(
'My foobar subject!!',
body,
'Darth Vader <notify#foobar.com>',
[the_user.email])
email = EmailMessage(
'My foobar subject!!',
render_to_string(
'emails/new_foobar_email.txt',
{
'foo': foo.something,
'bar': bar.something,
}
),
'darth#vader.com',
[the_user.email, ],
headers={'From': 'Darth Vader <darth#vader.com>'},
)
email.send(
fail_silently=False
)
The key thing I did wrong was having a trailing space after "From". So this will work.
However. I'm going to simplify the code and do as #Daniel Roseman suggested and put the display name in the from argument and not use the headers key words.

unknown RT error message

I'm trying to debug a script that's trying to talk to RT (Request Tracker) and I'm getting the following output:
RT/3.6.6 409 Syntax Error
# Syntax Error
>>ARRAY(0x2b3495f37750)
I have no idea what this error means in the context of RT given the astounding lack of detail making it difficult to debug. Here's the associated code for a little context, it's a script trying to create a ticket.
import requests
def combDicts(dicts):
out = {}
for d in dicts:
out.update(d)
return out
operPath = 'ticket/new'
credentials = {'user': 'myuser', 'pass': 'mypassword'}
content = {
'content': {
'id': 'ticket/new',
'Subject': 'Python Script Test',
'Queue': 'General - unassigned',
}
}
r = requests.post('https://rt.hdms.com/REST/1.0/' + operPath, params=combDicts((credentials, content)), verify = False)
print r.text
If I comment out all but the Queue line of the content dict the error changes to:
RT/3.6.6 409 Syntax Error
# Syntax Error
>> Queue
The crux of my question is this: Does anyone know what this error means or know where I can find documentation on what all the RT errors are and what could cause them?
You'll find much more information in the logs on the RT server itself, especially if you up the log level to debug. You might have better luck using one of the python libraries available for calling RT. However, the version of RT you're running is fairly old, released in Jan. 2008. You may have trouble using current libraries with an old version of RT.

XMPP chat: accessing contacts' status messages with xmppPy's Roster

I'm trying to access my google talk contacts' custom status messages with xmpppy. I'm made it this far:
import xmpp
import sys
userID = 'myname#gmail.com'
password = 'mypassword'
ressource = 'Script'
jid = xmpp.protocol.JID(userID)
jabber = xmpp.Client(jid.getDomain(), debug=[])
connection = jabber.connect(('talk.google.com',5222))
auth = jabber.auth(jid.getNode(), password, ressource)
jabber.sendInitPresence(requestRoster=1)
myroster = jabber.getRoster()
the roster object myroster now contains my contacts, but the custom status message is not included.
myroster.getStatus('oneofmyfriends#gmail.com')
returns None
looking at the 'raw roster', I can see that the resources dictionary is empty
u'oneofmyfriends#googlemail.com': {'ask': None, 'resources': {}, 'name': u'Some Name', 'groups': [], 'subscription': u'both'}
The weird thing is that I have gotten this to work today, but I the code might have been slightly different, but I can't figure out what exactly I did differently...
Any help would be greatly appreciated!
Cheers,
Martin
Here's one thing I've found, which was not clear to me when I first started working with xmpp. Friending is two-way.
Using presence stanzas
(a) You can "subscribe" to your friend, and your friend can return "subscribed".
(b) Your friend can "subscribe" to you, and you can return "subscribed".
Your friend will be in your roster if either (a) or (b) has happened.
You will be in your friends roster if either (a) or (b) has happened.
However...
You will not see their status unless you "subscribe" to your friend - (a) must happen
They will not see your status unless they "subscribe" to you - (b) must happen.
Most XMPP clients (pidgin, trillian, etc) will automatically make you send "subscribe" back to your friend when you send them "subscribed" (after they've sent you "subscribe"). XMPPPY does not do this out of the box. You must code it to do this.
This could explain why you weren't seeing status. Or if this doesn't cover your situation, it might be informative to someone else.
It's a timing issue. Add a handler with:
jabber.RegisterHandler('presence', myPresenceHandler)
def myPresenceHandler(self, con, event):
fromjid = event.getFrom().getStripped()
status = myroster.getStatus(fromjid)
BEFORE connecting. Then make sure to call jabber.Process() in a loop. The issue is that with your code, you'll sometimes receive presence stanzas before you look at the roster object, and sometimes after.

Categories

Resources