# How send "email" from code?

**URL:** <https://discuss.tryton.org/t/how-send-email-from-code/4864>\
**Category:** Developer\
**Created:** [December 16, 2021, 12:50pm UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864 "2021-12-16T12:50:37Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![JonatanGk](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/jonatangk/32/1686_2.png) [@JonatanGk](https://discuss.tryton.org/u/JonatanGk)\
**Post date:** [December 16, 2021, 12:50pm UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/1 "2021-12-16T12:50:37Z")

</div>

Hi again 😉 Ill try to explain the situation.  
My first try i try to create on “notification\_email” module an a new entry to send email to purchase petitioners when the purchase “state” change to processing. In my case each purchase line may come from two different petitioners, and i want to send diferent email to each one (only with own petition lines).  
On the notification\_email trigger i use “on update” but when purchase process, the purchase change the state but the trigger dont do nothing. I use diferent breakpoints on Trigger class but never go to this class. I think " On update" doesnt work properly, dont know exactly.

To try to solve my problem I try to implement replicating the same way that i can see on “tests” without success ☹

Accept ideas to solve this …

Actually i load the “record” on HTML template but …

code.

```auto
with Transaction().set_context(lines_to_email=lines):
                prueba = get_email(_REPORT, purchases[0], language)

            from_ = config.get('email', 'from')
            to_ = [employee]

            from email.mime.text import MIMEText
            msg = MIMEText(prueba, _charset='utf-8')
            msg['From'] = from_
            msg['To'] = to_
            msg['Cc'] = 'user@email.es'
            msg['Subject'] = Header('ENVIO FORZADOP', 'utf-8')
            msg['Auto-Submitted'] = 'auto-generated'
            msg['Message'] = prueba

            # sendmail_transactional(
            # from_, to_, msg, datamanager=datamanager)
            sendmail(from_, to_, msg)

```

```auto
Traceback (most recent call last):
  File "/home/jonatan/tryton/trytond/trytond/protocols/dispatcher.py", line 186, in _dispatch
    result = rpc.result(meth(*c_args, **c_kwargs))
  File "/home/jonatan/tryton/trytond/trytond/model/modelview.py", line 692, in wrapper
    return func(cls, records, *args, **kwargs)
  File "/home/jonatan/tryton/trytond/trytond/modules/electrans/purchase.py", line 113, in process
    super(Purchase, cls).process(purchases)
  File "/home/jonatan/tryton/trytond/trytond/modules/production_subcontract/production.py", line 305, in process
    super(Purchase, cls).process(purchases)
  File "/home/jonatan/tryton/trytond/trytond/model/modelview.py", line 692, in wrapper
    return func(cls, records, *args, **kwargs)
  File "/home/jonatan/tryton/trytond/trytond/modules/sale_supply/purchase.py", line 61, in wrapper
    func(cls, purchases)
  File "/home/jonatan/tryton/trytond/trytond/modules/sale_supply/purchase.py", line 74, in process
    super(Purchase, cls).process(purchases)
  File "/home/jonatan/tryton/trytond/trytond/model/modelview.py", line 692, in wrapper
    return func(cls, records, *args, **kwargs)
  File "/home/jonatan/tryton/trytond/trytond/modules/electrans_notification_email/purchase.py", line 48, in process
    msg = MIMEText(prueba, _charset='utf-8')
  File "/usr/lib/python3.8/email/mime/text.py", line 42, in __init__
    self.set_payload(_text, _charset)
  File "/usr/lib/python3.8/email/message.py", line 321, in set_payload
    self.set_charset(charset)
  File "/usr/lib/python3.8/email/message.py", line 364, in set_charset
    payload = payload.encode('ascii', 'surrogateescape')
AttributeError: 'tuple' object has no attribute 'encode'

```

Maybe exist any easy way, comment that my Tryton version is 5.2

& Thanks in advance 😉

---

<div class="post-metadata">

**Author:** ![pokoli](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/pokoli/32/22_2.png) [@pokoli](https://discuss.tryton.org/u/pokoli)\
**Post date:** [December 16, 2021, 1:26pm UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/2 "2021-12-16T13:26:57Z")

</div>

> [@JonatanGk](#):
>
> On the notification\_email trigger i use “on update” but when purchase process, the purchase change the state but the trigger dont do nothing. I use diferent breakpoints on Trigger class but never go to this class. I think " On update" doesnt work properly, dont know exactly.

You should use a “On write” trigger and test that the state is processing on condition. Something like:

```auto
Eval('self', {}).get('state') == 'processing

```

That should do the trick for sending the email when processing.

> [@JonatanGk](#):
>
> In my case each purchase line may come from two different petitioners, and i want to send diferent email to each one (only with own petition lines).

How do you store the petitioners on the line? If the petitioner is a Many2One to a known module the field should be already available as recipient on the notification trigger.

---

<div class="post-metadata">

**Author:** ![JonatanGk](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/jonatangk/32/1686_2.png) [@JonatanGk](https://discuss.tryton.org/u/JonatanGk)\
**Post date:** [December 17, 2021, 6:09am UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/3 "2021-12-17T06:09:46Z")

</div>

> [@pokoli](#):
>
> `Eval('self', {}).get('state') == 'processing`

Ill try thx

> [@pokoli](#):
>
> How do you store the petitioners on the line? If the petitioner is a Many2One to a known module the field should be already available as recipient on the notification trigger.

Get the petitioners not a problem :  
purchase.line \> purchase.request \> purchase.requisition \< petitioner

The problem of trigger as i try to explain is that in purchase i have for instance 3 lines, each line from diferent petitioner. I want to send 3 diferent mails to each one ( linked to them requisition).  
I tryed different ways to send email using html template (similar to notification\_email), but doesnt works.  
Maybe the On Write trigger works, but send a unique mail for all petitioners for instance, but no solve my problem. Dont know if u can help me to try to send a email from code?

Thanks again @pokoli🙂

---

<div class="post-metadata">

**Author:** ![pokoli](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/pokoli/32/22_2.png) [@pokoli](https://discuss.tryton.org/u/pokoli)\
**Post date:** [December 17, 2021, 8:17am UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/4 "2021-12-17T08:17:09Z")

</div>

Ok, so in your case you need to notify the employee of the requisition, which makes me think that the model triggering the email should be the requisition and not the purchase.

I will suggest adding a new field on requistion to know if the purchase have been processed (you will need to update it when processing the purchase) and then use the notification\_email module to send and email based on this new field.

This way each petitioner will receive an email for each of it’s requisitions when they are purchases.

Hope it helps!

---

<div class="post-metadata">

**Author:** ![JonatanGk](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/jonatangk/32/1686_2.png) [@JonatanGk](https://discuss.tryton.org/u/JonatanGk)\
**Post date:** [December 17, 2021, 8:34am UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/5 "2021-12-17T08:34:31Z")

</div>

Any way exist the posibilty that the requisition parcially completed. i would use this field but if for instance i complete a line and tomorrow completes the second line from same requistion. The trigger send me 2 email, first with 1 line and the following the first line + second. Can u understand me? dont know if i explained correctly.

Thanks again!

---

<div class="post-metadata">

**Author:** ![pokoli](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/pokoli/32/22_2.png) [@pokoli](https://discuss.tryton.org/u/pokoli)\
**Post date:** [December 17, 2021, 8:44am UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/6 "2021-12-17T08:44:48Z")

</div>

> [@JonatanGk](#):
>
> The trigger send me 2 email, first with 1 line and the following the first line + second. Can u understand me?

In such case, probably the best is to not update the field until it is fully completed, but if you need several emails you can have several states to trigger diferent emails.

It all depends on your needs.

---

<div class="post-metadata">

**Author:** ![JonatanGk](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/jonatangk/32/1686_2.png) [@JonatanGk](https://discuss.tryton.org/u/JonatanGk)\
**Post date:** [December 17, 2021, 10:23am UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/7 "2021-12-17T10:23:49Z")

</div>

I tryed to use the trigger with “On Write” & “On Update”, and i put several “breakpoints” into Trigger class. Always stop on breakpoint when i create a purchase requisition but never when update the state, the descriptions for instance…  
Maybe is a bug of 5.2 vers?

---

<div class="post-metadata">

**Author:** ![pokoli](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/pokoli/32/22_2.png) [@pokoli](https://discuss.tryton.org/u/pokoli)\
**Post date:** [December 17, 2021, 10:27am UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/8 "2021-12-17T10:27:01Z")

</div>

Which condition are you using?

---

<div class="post-metadata">

**Author:** ![JonatanGk](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/jonatangk/32/1686_2.png) [@JonatanGk](https://discuss.tryton.org/u/JonatanGk)\
**Post date:** [December 17, 2021, 10:56am UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/9 "2021-12-17T10:56:47Z")

</div>

[Equal(Get(Eval(‘self’, {}), ‘state’, ‘’), ‘done’)]  
But as i tell u i try to use in some breakpoint method that i think that Evaluate. Think that breakpoint places its correct because on create purchase requisition always stop but not on update.

Thx!

Edit: U think its posible to send mail by code??

---

<div class="post-metadata">

**Author:** ![ced](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/ced/32/1237_2.png) [@ced](https://discuss.tryton.org/u/ced)\
**Post date:** [December 17, 2021, 12:15pm UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/10 "2021-12-17T12:15:41Z")

</div>

> [@JonatanGk](#):
>
> tryed to use the trigger with “On Write” & “On Update”

For me we must first clarify something because there is no “On Update” on trigger.  
If you mean “On Time” then you should not check it because it is exclusive with “On Write”.

> [@JonatanGk](#):
>
> The problem of trigger as i try to explain is that in purchase i have for instance 3 lines, each line from diferent petitioner. I want to send 3 diferent mails to each one ( linked to them requisition).

So for me the trigger should be placed on the purchase line and not the purchase or maybe on the purchase requisition but it will need to setup some write that can be triggered.

---

<div class="post-metadata">

**Author:** ![JonatanGk](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/jonatangk/32/1686_2.png) [@JonatanGk](https://discuss.tryton.org/u/JonatanGk)\
**Post date:** [December 17, 2021, 12:49pm UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/11 "2021-12-17T12:49:53Z")

</div>

> [@ced](#):
>
> For me we must first clarify something because there is no “On Update” on trigger.  
> If you mean “On Time” then you should not check it because it is exclusive with “On Write”.

“On write” Sorry 🙂 i try to explain again with screenshoot.

 ![Screenshot_1](https://discuss-cdn.tryton.org/uploads/default/original/2X/d/d370ff68d73f385cff0bf09c1e698390e29b9f44.png)  
On create always send the mail but “On write” is never working. I tested with any breakpoint on Trigger methods and never pass through this code to check conditions of the trigger.  
I think that doesnt work properly maybe is an issue related to the version??

---

<div class="post-metadata">

**Author:** ![ced](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/ced/32/1237_2.png) [@ced](https://discuss.tryton.org/u/ced)\
**Post date:** [December 17, 2021, 12:59pm UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/12 "2021-12-17T12:59:24Z")

</div>

> [@JonatanGk](#):
>
> I tested with any breakpoint on Trigger methods and never pass through this code to check conditions of the trigger.

I guess you put the break point in the wrong place.  
The first point is that writing on the record should be checked by `ModelStorage.trigger_write_get_eligibles`.

---

<div class="post-metadata">

**Author:** ![JonatanGk](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/jonatangk/32/1686_2.png) [@JonatanGk](https://discuss.tryton.org/u/JonatanGk)\
**Post date:** [December 20, 2021, 8:47am UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/13 "2021-12-20T08:47:26Z")

</div>

> [@ced](#):
>
> `ModelStorage.trigger_write_get_eligibles`.

You were right! Following from that point what I have verified is that eval condition at first iteration response True when it should be FALSE, to at second iteration detect change.

[https://hg.tryton.org/trytond/file/5.2/trytond/model/modelstorage.py#l234](https://hg.tryton.org/trytond/file/5.2/trytond/model/modelstorage.py#l234)

I tryed some condition to change that first eval without success because the first iteration is returning always True.

Thanks again 🙂

---

<div class="post-metadata">

**Author:** ![ced](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/ced/32/1237_2.png) [@ced](https://discuss.tryton.org/u/ced)\
**Post date:** [December 20, 2021, 9:37am UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/14 "2021-12-20T09:37:18Z")

</div>

So you create the record with the condition already evaluated to True. In this case you must define the trigger to be “On Create” and “On Write” (which is a common practice).

---

<div class="post-metadata">

**Author:** ![JonatanGk](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/jonatangk/32/1686_2.png) [@JonatanGk](https://discuss.tryton.org/u/JonatanGk)\
**Post date:** [December 21, 2021, 1:45pm UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/15 "2021-12-21T13:45:34Z")

</div>

I created fer more triggers to try to understand how it works… But i never make it works…

> [@ced](#):
>
> ModelStorage.trigger\_write\_get\_eligibles.

Debugging from you pointed me i arrived to ir.trigger.Eval method whis is returning always true regardless the arguments

[https://hg.tryton.org/trytond/file/5.2/trytond/ir/trigger.py#l174](https://hg.tryton.org/trytond/file/5.2/trytond/ir/trigger.py#l174)

I think that the problem maybe is on env[‘self’] , because “EvalEnvironment(record, record. **class** )” is always returning “” (an empty string). It does not matter what model you pass an argument.  
I also saw that EvalEnvironment CLASS has changeD in the newest versions of Tryton so it make me think that maybe the issue can be related. Anyone can confirm me that on write triggers are working on v5.2?

---

<div class="post-metadata">

**Author:** ![ced](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/ced/32/1237_2.png) [@ced](https://discuss.tryton.org/u/ced)\
**Post date:** [December 21, 2021, 1:52pm UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/16 "2021-12-21T13:52:23Z")

</div>

I can confirm it is working on supported series (5.0, 6.0 and 6.2) see [https://drone.tryton.org/tryton/trytond](https://drone.tryton.org/tryton/trytond) for test\_on\_write.

---

<div class="post-metadata">

**Author:** ![JonatanGk](https://discuss-cdn.tryton.org/user_avatar/discuss.tryton.org/jonatangk/32/1686_2.png) [@JonatanGk](https://discuss.tryton.org/u/JonatanGk)\
**Post date:** [December 22, 2021, 12:41pm UTC](https://discuss.tryton.org/t/how-send-email-from-code/4864/17 "2021-12-22T12:41:33Z")

</div>

Hi again 😉 after we continue trying to do the trigger ‘write’ works. i see on newest versions of Tryton on triggers.py have a new method ‘\_record\_eval\_pyson(…’ I added this method on my triggers.py and I change the return value of “eval” function and “Voila!!” Works 🥳 🥳

Dont know if this solution u implemented on newest version. I leave the git diff by if u want to check.  
Again thx 😉

```auto
diff --git a/trytond/ir/trigger.py b/trytond/ir/trigger.py
index 2487307b..02938c50 100644
--- a/trytond/ir/trigger.py
+++ b/trytond/ir/trigger.py
@@ -7,6 +7,8 @@ from sql.aggregate import Count, Max
 
 from trytond.model.exceptions import ValidationError
 from trytond.i18n import gettext
+from trytond.pyson import PYSONEncoder
+
 from ..model import (
     ModelView, ModelSQL, DeactivableMixin, fields, EvalEnvironment, Check)
 from ..pyson import Eval, PYSONDecoder
@@ -172,7 +174,7 @@ class Trigger(DeactivableMixin, ModelSQL, ModelView):
         env['time'] = time
         env['context'] = Transaction().context
         env['self'] = EvalEnvironment(record, record. __class__ )
- return bool(PYSONDecoder(env).decode(trigger.condition))
+ return _record_eval_pyson(record, trigger.condition, True)
 
     @classmethod
     def trigger_action(cls, records, trigger):
@@ -304,3 +306,19 @@ class TriggerLog(ModelSQL):
 
         table = cls. __table_handler__ (module_name)
         table.index_action(['trigger', 'record_id'], 'add')
+
+
+def _record_eval_pyson(record, source, encoded=False):
+ transaction = Transaction()
+ if not encoded:
+ pyson = _pyson_encoder.encode(source)
+ else:
+ pyson = source
+ env = EvalEnvironment(record, record. __class__ )
+ env['context'] = transaction.context
+ env['active_model'] = record. __class__. __name__
+ env['active_id'] = record.id
+ return PYSONDecoder(env).decode(pyson)
+
+
+_pyson_encoder = PYSONEncoder()

```
